Changeset c7806122


Ignore:
Timestamp:
Sep 25, 2020, 6:15:27 PM (13 months ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast-unique-expr
Children:
bd47f35
Parents:
91fb850 (diff), 33f3cfb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Files:
3 added
23 edited

Legend:

Unmodified
Added
Removed
  • doc/LaTeXmacros/common.tex

    r91fb850 rc7806122  
    1111%% Created On       : Sat Apr  9 10:06:17 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri Sep  4 13:56:52 2020
    14 %% Update Count     : 383
     13%% Last Modified On : Wed Sep 23 21:21:55 2020
     14%% Update Count     : 454
    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}}
    7257
    7358\usepackage{pslatex}                                    % reduce size of san serif font
     
    244229\usepackage{listings}                                                                   % format program code
    245230\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
    246252
    247253\newcommand{\CFADefaults}{%
     
    262268belowskip=3pt,
    263269% replace/adjust listing characters that look bad in sanserif
    264 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
     270literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.75ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1
    265271        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    266272        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2,
    267 moredelim=**[is][\color{red}]{?}{?},    % red highlighting ?...? (registered trademark symbol) emacs: C-q M-.
     273}% lstset
     274}% CFADefaults
     275
     276\ifdefined\CFALatin%
     277\lstnewenvironment{cfa}[1][]{\CFADefaults
     278\lstset{
     279language=CFA,
     280moredelim=**[is][\color{red}]{®}{®},    % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
    268281moredelim=**[is][\color{blue}]{ß}{ß},   % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_
    269282moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"
    270283moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
     284% replace/adjust listing characters that look bad in sanserif
     285add to literate={`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    271286}% lstset
    272 }% CFADefaults
    273 \newcommand{\CFAStyle}{%
    274 \CFADefaults
     287\lstset{#1}
     288}{}
    275289% inline code ©...© (copyright symbol) emacs: C-q M-)
    276290\lstMakeShortInline©                                    % single-character for \lstinline
    277 }% CFAStyle
    278 
    279 \lstnewenvironment{cfa}[1][]
    280 {\CFADefaults\lstset{#1}}
    281 {}
     291\else% extra Latin-1 escape characters
     292\lstset{
     293language=CFA,
     294escapechar=\$,                                                  % LaTeX escape in CFA code
     295moredelim=**[is][\color{red}]{@}{@},    % red highlighting `...` (backtick symbol)
     296}% lstset
     297\lstnewenvironment{cfa}[1][]{\CFADefaults
     298\lstset{
     299language=CFA,
     300escapechar=\$,                                                  % LaTeX escape in CFA code
     301moredelim=**[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%
    282308
    283309% Local Variables: %
  • doc/LaTeXmacros/lstlang.sty

    r91fb850 rc7806122  
    88%% Created On       : Sat May 13 16:34:42 2017
    99%% Last Modified By : Peter A. Buhr
    10 %% Last Modified On : Tue Jan  8 14:40:33 2019
    11 %% Update Count     : 21
     10%% Last Modified On : Wed Sep 23 22:40:04 2020
     11%% Update Count     : 24
    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, _Generic, _Imaginary, __imag, __imag__,
     117                __float80, float80, __float128, float128, forall, ftype, generator, _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, thread,
     119                otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend, 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++}{}
     127\lstdefinelanguage{C++}[ANSI]{C++}{
     128        morekeywords={nullptr,}
     129}
    128130
    129131% uC++ programming language, based on ANSI C++
  • doc/refrat/refrat.tex

    r91fb850 rc7806122  
    1111%% Created On       : Wed Apr  6 14:52:25 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Wed Jan 31 17:30:23 2018
    14 %% Update Count     : 108
     13%% Last Modified On : Thu Sep 24 16:34:51 2020
     14%% Update Count     : 109
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
    32 \usepackage{xspace}
    3332\usepackage{varioref}                                                                   % extended references
    34 \usepackage{listings}                                                                   % format program code
    3533\usepackage[flushmargin]{footmisc}                                              % support label/reference in footnote
    3634\usepackage{latexsym}                                   % \Box glyph
    3735\usepackage{mathptmx}                                   % better math font with "times"
    3836\usepackage[usenames]{color}
    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 
     37\newcommand{\CFALatin}{}
    6438% inline code ©...© (copyright symbol) emacs: C-q M-)
    6539% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    6943% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    7044% 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}
    7162
    7263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    7364
     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
    7472% Names used in the document.
    75 \newcommand{\Version}{\input{../../version}}
     73\newcommand{\Version}{\input{build/version}}
    7674\newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}}
    7775\newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}}
  • doc/theses/andrew_beach_MMath/thesis.tex

    r91fb850 rc7806122  
    3434\usepackage[toc,abbreviations]{glossaries-extra}
    3535
    36 % Main glossary entries -- definitions of relevant terminology
    37 \newglossaryentry{computer}
    38 {
    39 name=computer,
    40 description={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 {
    49 type=nomenclature,
    50 name=dingledorf,
    51 description={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 {
    63 name={$\mathbf{v}$},
    64 sort={label},
    65 type=symbols,
    66 description={Random vector: a location in n-dimensional Cartesian space, where
    67                each dimensional component is determined by a random process}
    68 }
     36% Define all the glossaries.
     37\input{glossaries}
    6938
    7039% Generate the glossaries defined above.
  • doc/theses/fangren_yu_COOP_S20/Report.tex

    r91fb850 rc7806122  
    2626\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    2727\newcommand{\NOTE}{\textbf{NOTE}}
     28\newcommand{\TODO}[1]{{\color{Purple}#1}}
    2829
    2930\setlength{\topmargin}{-0.45in}                                                 % move running title into header
     
    3536\lstset{
    3637language=C++,                                                                                   % make C++ the default language
    37 escapechar=\$,                                                                                  % LaTeX escape in CFA code
    38 moredelim=**[is][\color{red}]{`}{`},
    3938}% lstset
    40 \lstMakeShortInline@%
    4139\lstnewenvironment{C++}[1][]                            % use C++ style
    42 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}}
    43 {}
     40{\lstset{language=C++,moredelim=**[is][\color{red}]{@}{@},#1}}{}
    4441
    4542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    8481\section{Overview}
    8582
    86 cfa-cc is the reference compiler for the \CFA programming language, which is a non-
    87 object-oriented extension to C.
    88 \CFA attempts to introduce productive modern programming language features to C
    89 while maintaining as much backward-compatibility as possible, so that most existing C
    90 programs can seamlessly work with \CFA.
    91 
    92 Since the \CFA project was dated back to the early 2000s, and only restarted in the past
    93 few years, there is a significant amount of legacy code in the current compiler codebase,
    94 with little proper documentation available. This becomes a difficulty while developing new
    95 features based on the previous implementations, and especially while diagnosing
    96 problems.
    97 
    98 Currently, the \CFA team is also facing another problem: bad compiler performance. For
    99 the development of a new programming language, writing a standard library is an
    100 important part. The incompetence of the compiler causes building the library files to take
    101 tens of minutes, making iterative development and testing almost impossible. There is
    102 ongoing effort to rewrite the core data structure of the compiler to overcome the
    103 performance issue, but many bugs may appear during the work, and lack of documentation
    104 makes debugging extremely difficult.
    105 
    106 This developer's reference will be continuously improved and eventually cover the
    107 compiler codebase. For now, the focus is mainly on the parts being rewritten, and also the
    108 performance bottleneck, namely the resolution algorithm. It is aimed to provide new
    109 developers to the project enough guidance and clarify the purposes and behavior of certain
    110 functions which are not mentioned in the previous \CFA research papers.
     83cfa-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
     86Since 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.
     87The lack of documentation makes it difficult to develop new features from the current implementation and diagnose problems.
     88
     89Currently, the \CFA team is also facing poor compiler performance.
     90For the development of a new programming language, writing standard libraries is an important component.
     91The slow compiler causes building of the library files to take tens of minutes, making iterative development and testing almost impossible.
     92There 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
     94This developer's reference manual begins the documentation and should be continuously im\-proved until it eventually covers the entire compiler codebase.
     95For now, the focus is mainly on the parts being rewritten, and also the primary performance bottleneck, namely the resolution algorithm.
     96Its 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}.
    11197
    11298
    11399\section{Compiler Framework}
    114100
     101\CFA source code is first transformed into an abstract syntax tree (AST) by the parser before analyzed by the compiler.
     102
     103
    115104\subsection{AST Representation}
    116105
    117 Source code input is first transformed into abstract syntax tree (AST) representation by the
    118 parser before analyzed by the compiler.
    119 
    120 There are 4 major categories of AST nodes used by the compiler, along with some derived
    121 structures.
    122 
    123 \subsubsection{Declaration nodes}
     106
     107There are 4 major categories of AST nodes used by the compiler, along with some derived structures.
     108
     109\subsubsection{Declaration Nodes}
    124110
    125111A declaration node represents either of:
    126112\begin{itemize}
    127113\item
    128 Type declaration: struct, union, typedef or type parameter (see Appendix A.3)
    129 \item
    130 Variable declaration
    131 \item
    132 Function declaration
     114type declaration: @struct@, @union@, @typedef@ or type parameter \TODO{(see Appendix A.3)}
     115\item
     116variable declaration
     117\item
     118function declaration
    133119\end{itemize}
    134120Declarations are introduced by standard C declarations, with the usual scoping rules.
    135 In addition, declarations can also be introduced by the forall clause (which is the origin
    136 of \CFA's name):
     121In addition, declarations can also be qualified by the \lstinline[language=CFA]@forall@ clause (which is the origin of \CFA's name):
    137122\begin{cfa}
    138 forall (<$\emph{TypeParameterList}$> | <$\emph{AssertionList}$>)
     123forall ( <$\emph{TypeParameterList}$> | <$\emph{AssertionList}$> )
    139124        $\emph{declaration}$
    140125\end{cfa}
    141 Type parameters in \CFA are similar to \CC template type parameters. The \CFA
    142 declaration
     126Type parameters in \CFA are similar to \CC template type parameters.
     127The \CFA declaration
    143128\begin{cfa}
    144129forall (dtype T) ...
    145130\end{cfa}
    146 behaves similarly as the \CC template declaration
     131behaves similarly to the \CC template declaration
    147132\begin{C++}
    148133template <typename T> ...
    149134\end{C++}
    150135
    151 Assertions are a distinctive feature of \CFA: contrary to the \CC template where
    152 arbitrary functions and operators can be used in a template definition, in a \CFA
    153 parametric function, operations on parameterized types must be declared in assertions.
    154 
     136Assertions are a distinctive feature of \CFA, similar to \emph{interfaces} in D and Go, and \emph{traits} in Rust.
     137Contrary 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.
    155138Consider the following \CC template:
    156139\begin{C++}
    157 template <typename T> int foo(T t) {
    158         return bar(t) + baz(t);
     140@template@ forall<typename T> T foo( T t ) {
     141        return t + t * t;
    159142}
    160143\end{C++}
    161 Unless bar and baz are also parametric functions taking any argument type, they must be
    162 declared in the assertions, or otherwise the code will not compile:
     144where there are no explicit requirements on the type @T@.
     145Therefore, the \CC compiler must deduce what operators are required during textual (macro) expansion of the template at each usage.
     146As a result, templates cannot be compiled.
     147\CFA assertions specify restrictions on type parameters:
    163148\begin{cfa}
    164 forall (dtype T | { int bar(T); int baz(t); }) int foo (T t) {
    165         return bar(t) + baz(t);
     149forall( dtype T | @{ T ?+?( T, T ); T ?*?( T, T ) }@ ) int foo ( T t ) {
     150        return t + t * t;
    166151}
    167152\end{cfa}
    168 Assertions are written using the usual function declaration syntax. The scope of type
    169 parameters and assertions is the following declaration.
    170 
    171 \subsubsection{Type nodes}
    172 
    173 A type node represents the type of an object or expression.
    174 Named types reference the corresponding type declarations. The type of a function is its
    175 function pointer type (same as standard C).
    176 With the addition of type parameters, named types may contain a list of parameter values
    177 (actual parameter types).
    178 
    179 \subsubsection{Statement nodes}
    180 
    181 Statement nodes represent the statements in the program, including basic expression
    182 statements, control flows and blocks.
     153Assertions are written using the usual \CFA function declaration syntax.
     154Only types with operators ``@+@'' and ``@*@'' work with this function, and the function prototype is sufficient to allow separate compilation.
     155
     156Type parameters and assertions are used in the following compiler data-structures.
     157
     158
     159\subsubsection{Type Nodes}
     160
     161Type nodes represent the type of an object or expression.
     162Named types reference the corresponding type declarations.
     163The type of a function is its function pointer type (same as standard C).
     164With the addition of type parameters, named types may contain a list of parameter values (actual parameter types).
     165
     166
     167\subsubsection{Statement Nodes}
     168
     169Statement nodes represent the executable statements in the program, including basic expression statements, control flows and blocks.
    183170Local declarations (within a block statement) are represented as declaration statements.
    184171
    185 \subsubsection{Expression nodes}
    186 
    187 Some expressions are represented differently in the compiler before and after resolution
    188 stage:
     172
     173\subsubsection{Expression Nodes}
     174
     175Some expressions are represented differently before and after the resolution stage:
    189176\begin{itemize}
    190177\item
    191 Name expressions: NameExpr pre-resolution, VariableExpr post-resolution
    192 \item
    193 Member expressions: UntypedMemberExpr pre-resolution, MemberExpr post-resolution
    194 \item
    195 Function call expressions (including overloadable operators): UntypedExpr pre-resolution, ApplicationExpr post-resolution
     178Name expressions: @NameExpr@ pre-resolution, @VariableExpr@ post-resolution
     179\item
     180Member expressions: @UntypedMemberExpr@ pre-resolution, @MemberExpr@ post-resolution
     181\item
     182\begin{sloppypar}
     183Function call expressions (including overloadable operators): @UntypedExpr@ pre-resolution, @ApplicationExpr@ post-resolution
     184\end{sloppypar}
    196185\end{itemize}
    197 The pre-resolution representations contain only the symbols. Post-resolution results link
    198 them to the actual variable and function declarations.
     186The pre-resolution representation contains only the symbols.
     187Post-resolution links them to the actual variable and function declarations.
    199188
    200189
    201190\subsection{Compilation Passes}
    202191
    203 Compilation steps are implemented as passes, which follows a general structural recursion
    204 pattern on the syntax tree.
    205 
    206 The basic work flow of compilation passes follows preorder and postorder traversal on
    207 tree data structure, implemented with visitor pattern, and can be loosely described with
    208 the following pseudocode:
    209 \begin{C++}
    210 Pass::visit (node_t node) {
    211         previsit(node);
    212         if (visit_children)
     192Compilation steps are implemented as passes, which follows a general structural recursion pattern on the syntax tree.
     193
     194The 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++}
     196Pass::visit( node_t node ) {
     197        previsit( node );
     198        if ( visit_children )
    213199                for each child of node:
    214                         child.accept(this);
    215         postvisit(node);
     200                        child.accept( this );
     201        postvisit( node );
    216202}
    217203\end{C++}
    218 Operations in previsit() happen in preorder (top to bottom) and operations in
    219 postvisit() happen in postorder (bottom to top). The precise order of recursive
    220 operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and
    221 @AST/Pass.impl.hpp@ (new).
    222 Implementations of compilation passes need to follow certain conventions:
     204Operations in @previsit@ happen in preorder (top to bottom) and operations in @postvisit@ happen in postorder (bottom to top).
     205The precise order of recursive operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and @AST/Pass.impl.hpp@ (new).
     206
     207Implementations of compilation passes follow certain conventions:
    223208\begin{itemize}
    224209\item
    225 Passes \textbf{should not} directly override the visit method (Non-virtual Interface
    226 principle); if a pass desires different recursion behavior, it should set
    227 @visit_children@ to false and perform recursive calls manually within previsit or
    228 postvisit procedures. To enable this option, inherit from @WithShortCircuiting@ mixin.
    229 \item
    230 previsit may mutate the node but \textbf{must not} change the node type or return null.
    231 \item
    232 postvisit may mutate the node, reconstruct it to a different node type, or delete it by
    233 returning null.
     210Passes \textbf{should not} directly override the visit method (Non-virtual Interface principle);
     211if a pass desires different recursion behaviour, it should set @visit_children@ to false and perform recursive calls manually within previsit or postvisit procedures.
     212To enable this option, inherit from the @WithShortCircuiting@ mixin.
     213\item
     214previsit may mutate the node but \textbf{must not} change the node type or return @nullptr@.
     215\item
     216postvisit may mutate the node, reconstruct it to a different node type, or delete it by returning @nullptr@.
    234217\item
    235218If the previsit or postvisit method is not defined for a node type, the step is skipped.
    236 If the return type is declared as void, the original node is returned by default. These
    237 behaviors are controlled by template specialization rules; see
    238 @Common/PassVisitor.proto.h@ (old) and @AST/Pass.proto.hpp@ (new) for details.
     219If the return type is declared as @void@, the original node is returned by default.
     220These behaviours are controlled by template specialization rules;
     221see @Common/PassVisitor.proto.h@ (old) and @AST/@ @Pass.proto.hpp@ (new) for details.
    239222\end{itemize}
    240223Other useful mixin classes for compilation passes include:
    241224\begin{itemize}
    242225\item
    243 WithGuards allows saving values of variables and restore automatically upon exiting
    244 the current node.
    245 \item
    246 WithVisitorRef creates a wrapped entity of current pass (the actual argument
    247 passed to recursive calls internally) for explicit recursion, usually used together
    248 with WithShortCircuiting.
    249 \item
    250 WithSymbolTable gives a managed symbol table with built-in scoping rule handling
    251 (\eg on entering and exiting a block statement)
     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)
    252231\end{itemize}
    253 \NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading
    254 resolution rules, it \textbf{must} explicitly introduce the inherited previsit and postvisit procedures
    255 to its own scope, or otherwise they will not be picked up by template resolution:
     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:
    256233\begin{C++}
    257234class Pass2: public Pass1 {
    258         using Pass1::previsit;
    259         using Pass1::postvisit;
     235        @using Pass1::previsit;@
     236        @using Pass1::postvisit;@
    260237        // new procedures
    261238}
     
    263240
    264241
    265 \subsection{Data Structure Change WIP (new-ast)}
    266 
    267 It has been observed that excessive copying of syntax tree structures accounts for a
    268 majority of computation cost and significantly slows down the compiler. In the previous
    269 implementation of the syntax tree, every internal node has a unique parent; therefore all
    270 copies are required to duplicate everything down to the bottom. A new, experimental
    271 re-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
    273 of common sub-structures and only makes copies when necessary.
    274 
    275 The 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
    277 used to detect sharing and allows optimization. For a purely functional (a.k.a. immutable)
    278 data structure, all mutations are modelled by shallow copies along the path of mutation.
     242\subsection{Data Structure Change (new-ast)}
     243
     244It has been observed that excessive copying of syntax tree structures accounts for a majority of computation cost and significantly slows down the compiler.
     245In the previous implementation of the syntax tree, every internal node has a unique parent;
     246therefore all copies are required to duplicate the entire subtree.
     247A 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
     249The 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.
     250Reference counting is used to detect sharing and allowing certain optimizations.
     251For a purely functional (immutable) data-structure, all mutations are modelled by shallow copies along the path of mutation.
    279252With reference counting optimization, unique nodes are allowed to be mutated in place.
    280 This however, may potentially introduce some complications and bugs; a few issues are
    281 discussed near the end of this section.
    282 
    283 \subsubsection{Source: AST/Node.hpp}
    284 
    285 class @ast::Node@ is the base class of all new-ast node classes, which implements
    286 reference counting mechanism. Two different counters are recorded: ``strong'' reference
    287 count for number of nodes semantically owning it; ``weak'' reference count for number of
    288 nodes holding a mere reference and only need to observe changes.
    289 class @ast::ptr_base@ is the smart pointer implementation and also takes care of
    290 resource management.
    291 
    292 Direct access through the smart pointer is read-only. A mutable access should be obtained
    293 by calling shallowCopy or mutate as below.
    294 
    295 Currently, the weak pointers are only used to reference declaration nodes from a named
    296 type, or a variable expression. Since declaration nodes are intended to denote unique
    297 entities in the program, weak pointers always point to unique (unshared) nodes. This may
    298 change in the future, and weak references to shared nodes may introduce some problems;
     253This however, may potentially introduce some complications and bugs;
     254a few issues are discussed near the end of this section.
     255
     256
     257\subsubsection{Source: \lstinline{AST/Node.hpp}}
     258
     259Class @ast::Node@ is the base class of all new-ast node classes, which implements reference counting mechanism.
     260Two 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.
     262Class @ast::ptr_base@ is the smart pointer implementation and also takes care of resource management.
     263
     264Direct access through the smart pointer is read-only.
     265A mutable access should be obtained by calling @shallowCopy@ or mutate as below.
     266
     267Currently, the weak pointers are only used to reference declaration nodes from a named type, or a variable expression.
     268Since declaration nodes are intended to denote unique entities in the program, weak pointers always point to unique (unshared) nodes.
     269This property may change in the future, and weak references to shared nodes may introduce some problems;
    299270see mutate function below.
    300271
    301 All node classes should always use smart pointers in the structure and should not use raw
    302 pointers.
    303 
     272All node classes should always use smart pointers in structure definitions versus raw pointers.
     273Function
    304274\begin{C++}
    305275void ast::Node::increment(ref_type ref)
    306276\end{C++}
    307 Increments this node's strong or weak reference count.
     277increments this node's strong or weak reference count.
     278Function
    308279\begin{C++}
    309280void ast::Node::decrement(ref_type ref, bool do_delete = true)
    310281\end{C++}
    311 Decrements this node's strong or weak reference count. If strong reference count reaches
    312 zero, the node is deleted by default.
    313 \NOTE: Setting @do_delete@ to false may result in a detached node. Subsequent code should
    314 manually delete the node or assign it to a strong pointer to prevent memory leak.
     282decrements this node's strong or weak reference count.
     283If strong reference count reaches zero, the node is deleted.
     284\NOTE: Setting @do_delete@ to false may result in a detached node.
     285Subsequent code should manually delete the node or assign it to a strong pointer to prevent memory leak.
     286
    315287Reference counting functions are internally called by @ast::ptr_base@.
     288Function
    316289\begin{C++}
    317290template<typename node_t>
    318291node_t * shallowCopy(const node_t * node)
    319292\end{C++}
    320 Returns a mutable, shallow copy of node: all child pointers are pointing to the same child
    321 nodes.
     293returns a mutable, shallow copy of node: all child pointers are pointing to the same child nodes.
     294Function
    322295\begin{C++}
    323296template<typename node_t>
    324297node_t * mutate(const node_t * node)
    325298\end{C++}
    326 If node is unique (strong reference count is 1), returns a mutable pointer to the same node.
    327 Otherwise, returns shallowCopy(node).
    328 It is an error to mutate a shared node that is weak-referenced. Currently this does not
    329 happen. The problem may appear once weak pointers to shared nodes (\eg expression
    330 nodes) 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
    333 issue is presented at the end of this section.
     299returns a mutable pointer to the same node, if the node is unique (strong reference count is 1);
     300otherwise, it returns @shallowCopy(node)@.
     301It is an error to mutate a shared node that is weak-referenced.
     302Currently this does not happen.
     303A problem may appear once weak pointers to shared nodes (\eg expression nodes) are used;
     304special care is needed.
     305
     306\NOTE: This naive uniqueness check may not be sufficient in some cases.
     307A discussion of the issue is presented at the end of this section.
     308Functions
    334309\begin{C++}
    335310template<typename node_t, typename parent_t, typename field_t, typename assn_t>
    336 const node_t * mutate_field(const node_t * node, field_t parent_t::*field, assn_t && val)
     311const node_t * mutate_field(const node_t * node, field_t parent_t::* field, assn_t && val)
    337312\end{C++}
    338313\begin{C++}
     
    342317                field_t && val)
    343318\end{C++}
    344 Helpers for mutating a field on a node using pointer to member (creates shallow copy
    345 when necessary).
    346 
    347 \subsubsection{Issue: Undetected sharing}
    348 
    349 The @mutate@ behavior described above has a problem: deeper shared nodes may be
     319are 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
     324The @mutate@ behaviour described above has a problem: deeper shared nodes may be
    350325mistakenly considered as unique. \VRef[Figure]{f:DeepNodeSharing} shows how the problem could arise:
    351326\begin{figure}
     
    355330\label{f:DeepNodeSharing}
    356331\end{figure}
    357 Suppose that we are working on the tree rooted at P1, which
    358 is logically the chain P1-A-B and P2 is irrelevant, and then
    359 mutate(B) is called. The algorithm considers B as unique since
    360 it is only directly owned by A. However, the other tree P2-A-B
    361 indirectly shares the node B and is therefore wrongly mutated.
    362 
    363 To partly address this problem, if the mutation is called higher up the tree, a chain
    364 mutation helper can be used:
    365 
    366 \subsubsection{Source: AST/Chain.hpp}
    367 
     332Given the tree rooted at P1, which is logically the chain P1-A-B, and P2 is irrelevant, assume @mutate(B)@ is called.
     333The algorithm considers B as unique since it is only directly owned by A.
     334However, the other tree P2-A-B indirectly shares the node B and is therefore wrongly mutated.
     335
     336To 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
     340Function
    368341\begin{C++}
    369342template<typename node_t, Node::ref_type ref_t>
    370343auto chain_mutate(ptr_base<node_t, ref_t> & base)
    371344\end{C++}
    372 This function returns a chain mutator handle which takes pointer-to-member to go down
    373 the tree while creating shallow copies as necessary; see @struct _chain_mutator@ in the
    374 source code for details.
    375 
    376 For example, in the above diagram, if mutation of B is wanted while at P1, the call using
    377 @chain_mutate@ looks like the following:
     345returns a chain mutator handle that takes pointer-to-member to go down the tree, while creating shallow copies as necessary;
     346see @struct _chain_mutator@ in the source code for details.
     347
     348For example, in the above diagram, if mutation of B is wanted while at P1, the call using @chain_mutate@ looks like the following:
    378349\begin{C++}
    379350chain_mutate(P1.a)(&A.b) = new_value_of_b;
    380351\end{C++}
    381 Note that if some node in chain mutate is shared (therefore shallow copied), it implies that
    382 every node further down will also be copied, thus correctly executing the functional
    383 mutation algorithm. This example code creates copies of both A and B and performs
    384 mutation on the new nodes, so that the other tree P2-A-B is untouched.
    385 However, 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
    387 experimental use with the resolver algorithm, which mostly rebuilds the tree bottom-up,
    388 this issue does not actually happen. It should be addressed in the future when other
    389 compilation passes are migrated to new-ast and many of them contain procedural
    390 mutations, 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 ???
     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.
     353This 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.
     354However, if a pass traverses down to node B and performs mutation, for example, in @postvisit(B)@, information on sharing higher up is lost.
     355Since 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.
     356It 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
    395359\section{Compiler Algorithm Documentation}
    396360
    397 This documentation currently covers most of the resolver, data structures used in variable
    398 and expression resolution, and a few directly related passes. Later passes involving code
    399 generation is not included yet; documentation for those will be done afterwards.
     361This compiler algorithm documentation covers most of the resolver, data structures used in variable and expression resolution, and a few directly related passes.
     362Later passes involving code generation are not included yet;
     363documentation for those will be done latter.
     364
    400365
    401366\subsection{Symbol Table}
    402367
    403 \NOTE: For historical reasons, the symbol table data structure was called ``indexer'' in the
    404 old implementation. Hereby we will be using the name SymbolTable everywhere.
    405 The symbol table stores a mapping from names to declarations and implements a similar
    406 name 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
    407 name space rule is that typedef aliases are no longer considered ordinary identifiers.
    408 In addition to C tag types (struct, union, enum), \CFA introduces another tag type, trait,
    409 which is a named collection of assertions.
    410 
    411 \subsubsection{Source: AST/SymbolTable.hpp}
    412 
    413 \subsubsection{Source: SymTab/Indexer.h}
    414 
     368\NOTE: For historical reasons, the symbol-table data-structure is called @indexer@ in the old implementation.
     369Hereby, the name is changed to @SymbolTable@.
     370The 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.}
     371The difference in name-space rule is that @typedef@ aliases are no longer considered ordinary identifiers.
     372In 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
     382Function
    415383\begin{C++}
    416384SymbolTable::addId(const DeclWithType * decl)
    417385\end{C++}
    418 Since \CFA allows overloading of variables and functions, ordinary identifier names need
    419 to 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
    420 making adaptations to \CFA specific features, mainly assertions and overloaded variables
    421 by type. Naming conflicts are handled by mangled names; lookup by name returns a list of
    422 declarations with the same literal identifier name.
    423 
     386provides name mangling of identifiers, since \CFA allows overloading of variables and functions.
     387The 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
     389Naming conflicts are handled by mangled names;
     390lookup by name returns a list of declarations with the same identifier name.
     391Functions
    424392\begin{C++}
    425393SymbolTable::addStruct(const StructDecl * decl)
     
    428396SymbolTable::addTrait(const TraitDecl * decl)
    429397\end{C++}
    430 Adds a tag type declaration to the symbol table.
     398add a tag-type declaration to the symbol table.
     399Function
    431400\begin{C++}
    432401SymbolTable::addType(const NamedTypeDecl * decl)
    433402\end{C++}
    434 Adds a typedef alias to the symbol table.
    435 
    436 \textbf{C Incompatibility Note}: Since Cforall allows using struct, union and enum type names
    437 without the keywords, typedef names and tag type names cannot be disambiguated by
    438 syntax rules. Currently the compiler puts them together and disallows collision. The
    439 following program is valid C but not valid Cforall:
     403adds 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.
     406Currently the compiler puts them together and disallows collision.
     407The following program is valid C but invalid \CFA (and \CC):
    440408\begin{C++}
    441409struct A {};
     410typedef int A; // gcc: ok, cfa: Cannot redefine typedef A
     411struct A sa; // C disambiguates via struct prefix
     412A ia;
     413\end{C++}
     414In practices, such usage is extremely rare, and hence, this change (as in \CC) has minimal impact on existing C programs.
     415The declaration
     416\begin{C++}
     417struct A {};
     418typedef struct A A; // A is an alias for struct A
     419A a;
     420struct A b;
     421\end{C++}
     422is not an error because the alias name is identical to the original.
     423Finally, the following program is allowed in \CFA:
     424\begin{C++}
    442425typedef int A;
    443 // gcc: ok, cfa: Cannot redefine typedef A
    444 \end{C++}
    445 In actual practices however, such usage is extremely rare, and typedef struct A A; is
    446 not considered an error, but silently discarded. Therefore, we expect this change to have
    447 minimal impact on existing C programs.
    448 Meanwhile, the following program is allowed in Cforall:
    449 \begin{C++}
    450 typedef int A;
    451 void A();
     426void A(); // name mangled
    452427// gcc: A redeclared as different kind of symbol, cfa: ok
    453428\end{C++}
     429because the function name is mangled.
     430
    454431
    455432\subsection{Type Environment and Unification}
    456433
    457 The core of parametric type resolution algorithm.
    458 Type Environment organizes type parameters in \textbf{equivalent classes} and maps them to
    459 actual types. Unification is the algorithm that takes two (possibly parametric) types and
    460 parameter mappings and attempts to produce a common type by matching the type
    461 environments.
     434The following core ideas underlie the parametric type-resolution algorithm.
     435A type environment organizes type parameters into \textbf{equivalent classes} and maps them to actual types.
     436Unification 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.
    462437
    463438The unification algorithm is recursive in nature and runs in two different modes internally:
    464439\begin{itemize}
    465440\item
    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
    469 common type.
     441Exact unification mode requires equivalent parameters to match perfectly.
     442\item
     443Inexact unification mode allows equivalent parameters to be converted to a common type.
    470444\end{itemize}
    471 For 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 
    474 Within inexact mode, types are allowed to differ on their cv-qualifiers; additionally, if a
    475 type never appear either in parameter list or as the base type of a pointer, it may also be
    476 widened (i.e. safely converted). As Cforall currently does not implement subclassing similar
    477 to object-oriented languages, widening conversions are on primitive types only, for
    478 example the conversion from int to long.
    479 
    480 The need for two unification modes come from the fact that parametric types are
    481 considered compatible only if all parameters are exactly the same (not just compatible).
    482 Pointer types also behaves similarly; in fact, they may be viewed as a primitive kind of
    483 parametric types. @int*@ and @long*@ are different types, just like @vector(int)@ and
    484 @vector(long)@ are, for the parametric type @vector(T)@.
    485 
    486 The resolver should use the following ``@public@'' functions:\footnote{
    487 Actual code also tracks assertions on type parameters; those extra arguments are omitted here for
    488 conciseness.}
    489 
    490 
    491 \subsubsection{Source: ResolvExpr/Unify.cc}
    492 
    493 \begin{C++}
    494 bool unify(const Type *type1, const Type *type2, TypeEnvironment &env,
    495 OpenVarSet &openVars, const SymbolTable &symtab, Type *&commonType)
    496 \end{C++}
    497 Attempts to unify @type1@ and @type2@ with current type environment.
    498 
    499 If operation succeeds, @env@ is modified by combining the equivalence classes of matching
    500 parameters in @type1@ and @type2@, and their common type is written to commonType.
    501 
    502 If operation fails, returns false.
    503 \begin{C++}
    504 bool typesCompatible(const Type * type1, const Type * type2, const
    505 SymbolTable &symtab, const TypeEnvironment &env)
    506 bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type *
    507 type2, const SymbolTable &symtab, const TypeEnvironment &env)
    508 \end{C++}
    509 
    510 Determines if type1 and type2 can possibly be the same type. The second version ignores
    511 the outermost cv-qualifiers if present.\footnote{
    512 In const \lstinline@int * const@, only the second \lstinline@const@ is ignored.}
    513 
    514 The call has no side effect.
    515 
    516 \NOTE: No attempts are made to widen the types (exact unification is used), although the
    517 function names may suggest otherwise. E.g. @typesCompatible(int, long)@ returns false.
     445For 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
     447Within the inexact mode, types are allowed to differ on their cv-qualifiers (\eg @const@, @volatile@, \etc);
     448additionally, 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).
     449As \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
     451The 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).
     452Pointer types also behaves similarly;
     453in 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
     456The resolver uses the following @public@ functions:\footnote{
     457Actual 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
     462Function
     463\begin{C++}
     464bool unify(const Type * type1, const Type * type2, TypeEnvironment & env,
     465        OpenVarSet & openVars, const SymbolTable & symtab, Type *& commonType)
     466\end{C++}
     467returns a boolean indicating if the unification succeeds or fails after attempting to unify @type1@ and @type2@ within current type environment.
     468If 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@.
     469If the unify fails, nothing changes.
     470Functions
     471\begin{C++}
     472bool typesCompatible(const Type * type1, const Type * type2, const SymbolTable & symtab,
     473        const TypeEnvironment & env)
     474bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type * type2,
     475        const SymbolTable & symtab, const TypeEnvironment & env)
     476\end{C++}
     477return a boolean indicating if types @type1@ and @type2@ can possibly be the same type.
     478The second version ignores the outermost cv-qualifiers if present.\footnote{
     479In \lstinline@const int * const@, only the second \lstinline@const@ is ignored.}
     480These 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.
    518483
    519484
    520485\subsection{Expression Resolution}
    521486
    522 The design of the current version of expression resolver is outlined in the Ph.D. Thesis from
    523 Aaron Moss~\cite{Moss19}.
    524 
     487The design of the current version of expression resolver is outlined in the Ph.D.\ thesis by Aaron Moss~\cite{Moss19}.
    525488A summary of the resolver algorithm for each expression type is presented below.
    526489
    527 All overloadable operators are modelled as function calls. For a function call,
    528 interpretations of the function and arguments are found recursively. Then the following
    529 steps produce a filtered list of valid interpretations:
     490All overloadable operators are modelled as function calls.
     491For a function call, interpretations of the function and arguments are found recursively.
     492Then the following steps produce a filtered list of valid interpretations:
    530493\begin{enumerate}
    531494\item
    532 From all possible combinations of interpretations of the function and arguments,
    533 those where argument types may be converted to function parameter types are
    534 considered valid.
     495From all possible combinations of interpretations of the function and arguments, those where argument types may be converted to function parameter types are considered valid.
    535496\item
    536497Valid interpretations with the minimum sum of argument costs are kept.
    537498\item
    538 Argument costs are then discarded; the actual cost for the function call expression is
    539 the sum of conversion costs from the argument types to parameter types.
    540 \item
    541 For each return type, the interpretations with satisfiable assertions are then sorted
    542 by actual cost computed in step 3. If for a given type, the minimum cost
    543 interpretations are not unique, it is said that for that return type the interpretation
    544 is ambiguous. If the minimum cost interpretation is unique but contains an
    545 ambiguous argument, it is also considered ambiguous.
     499\label{p:argcost}
     500Argument 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}
     503For each return type, the interpretations with satisfiable assertions are then sorted by actual cost computed in step~\ref{p:argcost}.
     504If for a given type, the minimum cost interpretations are not unique, that return type is ambiguous.
     505If the minimum cost interpretation is unique but contains an ambiguous argument, it is also ambiguous.
    546506\end{enumerate}
    547 Therefore, for each return type, the resolver produces either of:
     507Therefore, for each return type, the resolver produces:
    548508\begin{itemize}
    549509\item
    550 No alternatives
    551 \item
    552 A single valid alternative
    553 \item
    554 An ambiguous alternative
     510no alternatives
     511\item
     512a single valid alternative
     513\item
     514an ambiguous alternative
    555515\end{itemize}
    556 Note that an ambiguous alternative may be discarded at the parent expressions because a
    557 different return type matches better for the parent expressions.
    558 
    559 The non-overloadable expressions in Cforall are: cast expressions, address-of (unary @&@)
    560 expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional
    561 expression (@?:@).
    562 
    563 For a cast expression, the convertible argument types are kept. Then the result is selected
    564 by lowest argument cost, and further by lowest conversion cost to target type. If the lowest
    565 cost is still not unique, or an ambiguous argument interpretation is selected, the cast
    566 expression is ambiguous. In an expression statement, the top level expression is implicitly
    567 cast to void.
     516\NOTE: an ambiguous alternative may be discarded at the parent expressions because a different return type matches better for the parent expressions.
     517
     518The \emph{non}-overloadable expressions in \CFA are: cast expressions, address-of (unary @&@) expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional expression (@?:@).
     519
     520For a cast expression, the convertible argument types are kept.
     521Then the result is selected by lowest argument cost, and further by lowest conversion cost to target type.
     522If the lowest cost is still not unique or an ambiguous argument interpretation is selected, the cast expression is ambiguous.
     523In an expression statement, the top level expression is implicitly cast to @void@.
    568524
    569525For an address-of expression, only lvalue results are kept and the minimum cost is selected.
    570526
    571 For logical expressions @&&@ and @||@, arguments are implicitly cast to bool, and follow the rule
    572 of cast expression as above.
    573 
    574 For the ternary conditional expression, the condition is implicitly cast to bool, and the
    575 branch expressions must have compatible types. Each pair of compatible branch
    576 expression types produce a possible interpretation, and the cost is defined as the sum of
    577 expression costs plus the sum of conversion costs to the common type.
    578 
    579 TODO: Write a specification for expression costs.
     527For logical expressions @&&@ and @||@, arguments are implicitly cast to @bool@, and follow the rules fr cast expression above.
     528
     529For the ternary conditional expression, the condition is implicitly cast to @bool@, and the branch expressions must have compatible types.
     530Each 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.}
    580533
    581534
    582535\subsection{Assertion Satisfaction}
    583536
    584 The resolver tries to satisfy assertions on expressions only when it is needed: either while
    585 selecting from multiple alternatives of a same result type for a function call (step 4 of
    586 resolving function calls), or upon reaching the top level of an expression statement.
    587 
    588 Unsatisfiable alternatives are discarded. Satisfiable alternatives receive \textbf{implicit
    589 parameters}: in Cforall, parametric functions are designed such that they can be compiled
    590 separately, as opposed to \CC templates which are only compiled at instantiation. Given a
    591 parametric function definition:
     537The 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
     539Unsatisfiable alternatives are discarded.
     540Satisfiable alternatives receive \textbf{implicit parameters}: in \CFA, parametric functions may be separately compiled, as opposed to \CC templates which are only compiled at instantiation.
     541Given the parametric function-definition:
    592542\begin{C++}
    593543forall (otype T | {void foo(T);})
    594544void bar (T t) { foo(t); }
    595545\end{C++}
    596 The function bar does not know which @foo@ to call when compiled without knowing the call
    597 site, so it requests a function pointer to be passed as an extra argument. At the call site,
    598 implicit parameters are automatically inserted by the compiler.
    599 
    600 \textbf{TODO}: Explain how recursive assertion satisfaction and polymorphic recursion work.
     546the 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.
     547At the call site, implicit parameters are automatically inserted by the compiler.
     548
     549\TODO{Explain how recursive assertion satisfaction and polymorphic recursion work.}
    601550
    602551
     
    605554\subsection{Test Suites}
    606555
    607 Automatic test suites are located under the @tests/@ directory. A test case consists of an
    608 input CFA source file (name ending with @.cfa@), and an expected output file located
    609 in @.expect/@ directory relative to the source file, with the same file name ending with @.txt@.
    610 So a test named @tuple/tupleCast@ has the following files, for example:
     556Automatic test suites are located under the @tests/@ directory.
     557A 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@.
     558For example, the test named @tests/tuple/tupleCast.cfa@ has the following files, for example:
    611559\begin{C++}
    612560tests/
    613 ..     tuple/
    614 ......     .expect/
    615 ..........       tupleCast.txt
    616 ......     tupleCast.cfa
    617 \end{C++}
    618 If compilation fails, the error output is compared to the expect file. If compilation succeeds,
    619 the built program is run and its output compared to the expect file.
    620 To run the tests, execute the test script @test.py@ under the @tests/@ directory, with a list of
    621 test names to be run, or @--all@ to run all tests. The test script reports test cases
    622 fail/success, compilation time and program run time.
     561        tuple/
     562                .expect/
     563                        tupleCast.txt
     564                tupleCast.cfa
     565\end{C++}
     566If compilation fails, the error output is compared to the expect file.
     567If the compilation succeeds but does not generate an executable, the compilation output is compared to the expect file.
     568If the compilation succeeds and generates an executable, the executable is run and its output is compared to the expect file.
     569To 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.
     570The test script reports test cases fail/success, compilation time and program run time.
     571To see all the options available for @test.py@ using the @--help@ option.
    623572
    624573
    625574\subsection{Performance Reports}
    626575
    627 To turn on performance reports, pass @-S@ flag to the compiler.
    628 
    629 3 kinds of performance reports are available:
     576To turn on performance reports, pass the @-XCFA -S@ flag to the compiler.
     577Three kinds of performance reports are available:
    630578\begin{enumerate}
    631579\item
     
    639587@Common/Stats/Counter.h@.
    640588\end{enumerate}
    641 It is suggested to run performance tests with optimized build (@g++@ flag @-O3@)
     589It is suggested to run performance tests with optimization (@g++@ flag @-O3@).
    642590
    643591
  • doc/user/user.tex

    r91fb850 rc7806122  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Fri Mar  6 13:34:52 2020
    14 %% Update Count     : 3924
     13%% Last Modified On : Thu Sep 24 16:34:52 2020
     14%% Update Count     : 3997
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    3030\usepackage{upquote}                                                                    % switch curled `'" to straight
    3131\usepackage{calc}
    32 \usepackage{xspace}
    3332\usepackage{varioref}                                                                   % extended references
    34 \usepackage{listings}                                                                   % format program code
     33\usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig}
     34\renewcommand{\thesubfigure}{\alph{subfigure})}
    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 \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 
     39\newcommand{\CFALatin}{}
    6340% inline code ©...© (copyright symbol) emacs: C-q M-)
    6441% red highlighting ®...® (registered trademark symbol) emacs: C-q M-.
     
    6845% keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^
    6946% 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}
    7075
    7176%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    7984\newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}}
    8085\newcommand{\KWC}{K-W C\xspace}
    81 
    82 \newsavebox{\LstBox}
    8386
    8487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    253256
    254257The 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):
    255 \begin{lstlisting}
     258\begin{cfa}
    256259®forall( otype T )® T identity( T val ) { return val; }
    257260int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§
    258 \end{lstlisting}
     261\end{cfa}
    259262% extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions.
    260263\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}.
     
    275278\begin{comment}
    276279A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array:
    277 \begin{lstlisting}
     280\begin{cfa}
    278281void * bsearch( const void * key, const void * base, size_t dim, size_t size,
    279282                                int (* compar)( const void *, const void * ));
     
    284287double key = 5.0, vals[10] = { /* 10 sorted floating values */ };
    285288double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§
    286 \end{lstlisting}
     289\end{cfa}
    287290which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers:
    288 \begin{lstlisting}
     291\begin{cfa}
    289292forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) {
    290293        int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ }
     
    297300double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§
    298301int posn = bsearch( 5.0, vals, 10 );
    299 \end{lstlisting}
     302\end{cfa}
    300303The nested function ©comp© provides the hidden interface from typed \CFA to untyped (©void *©) C, plus the cast of the result.
    301304Providing a hidden ©comp© function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope.
     
    305308\CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations.
    306309For example, it is possible to write a type-safe \CFA wrapper ©malloc© based on the C ©malloc©:
    307 \begin{lstlisting}
     310\begin{cfa}
    308311forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    309312int * ip = malloc(); §\C{// select type and size from left-hand side}§
    310313double * dp = malloc();
    311314struct S {...} * sp = malloc();
    312 \end{lstlisting}
     315\end{cfa}
    313316where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    314317\end{comment}
     
    943946the same level as a ©case© clause; the target label may be case ©default©, but only associated
    944947with the current ©switch©/©choose© statement.
    945 
    946 
    947 \subsection{Loop Control}
    948 
    949 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
    950 \begin{itemize}
    951 \item
    952 The 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
    954 An empty conditional implies comparison value of ©1© (true).
    955 \item
    956 A comparison N is implicit up-to exclusive range [0,N©®)®©.
    957 \item
    958 A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
    959 \item
    960 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
    961 \item
    962 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
    963 \item
    964 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
    965 \item
    966 The 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
    972 The up-to range uses operator ©+=© for increment;
    973 \item
    974 The 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}
    980948
    981949\begin{figure}
     
    10861054
    10871055
     1056\subsection{Loop Control}
     1057
     1058The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).
     1059\begin{itemize}
     1060\item
     1061The 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
     1063An empty conditional implies comparison value of ©1© (true).
     1064\item
     1065A comparison N is implicit up-to exclusive range [0,N©®)®©.
     1066\item
     1067A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.
     1068\item
     1069The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.
     1070\item
     1071The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.
     1072\item
     1073The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.
     1074\item
     1075The 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
     1081The up-to range uses operator ©+=© for increment;
     1082\item
     1083The 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
    10881091%\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}}
    10891092\subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}}
     
    10951098for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement.
    10961099\VRef[Figure]{f:MultiLevelExit} shows ©continue© and ©break© indicating the specific control structure, and the corresponding C program using only ©goto© and labels.
    1097 The innermost loop has 7 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
     1100The innermost loop has 8 exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.
    10981101
    10991102\begin{figure}
    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
     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
    11231130} // compound
    11241131\end{cfa}
    1125 &
    1126 \begin{cfa}
     1132\end{lrbox}
     1133
     1134\begin{lrbox}{\myboxB}
     1135\begin{cfa}[tabsize=3]
    11271136{
    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}
     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}
    11741169\caption{Multi-level Exit}
    11751170\label{f:MultiLevelExit}
     
    14261421try {
    14271422        f(...);
    1428 } catch( E e ; §boolean-predicate§ ) {          §\C[8cm]{// termination handler}§
     1423} catch( E e ; §boolean-predicate§ ) {          §\C{// termination handler}§
    14291424        // recover and continue
    1430 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}\CRT§
     1425} catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}§
    14311426        // repair and return
    14321427} finally {
     
    34913486For 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.
    34923487\begin{cquote}
    3493 \begin{lrbox}{\LstBox}
     3488\begin{lrbox}{\myboxA}
    34943489\begin{cfa}[aboveskip=0pt,belowskip=0pt]
    34953490int x;   double y   char z;
     
    34973492\end{lrbox}
    34983493\begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{3em}}l@{}}
    3499 \multicolumn{1}{@{}l@{}}{\usebox\LstBox} \\
     3494\multicolumn{1}{@{}l@{}}{\usebox\myboxA} \\
    35003495\multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}}        & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}}       & \multicolumn{1}{c}{\textbf{Python}}   \\
    35013496\begin{cfa}[aboveskip=0pt,belowskip=0pt]
     
    66726667For 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.
    66736668Without 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}
    66746672
    66756673\CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in
     
    67216719
    67226720        // §\CFA§ safe general allocation, fill, resize, alignment, array
    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 );
     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}§
    67436743
    67446744        // §\CFA§ safe initialization/copy, i.e., implicit size specification
  • src/AST/Convert.cpp

    r91fb850 rc7806122  
    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
    179194                auto decl = new FunctionDecl(
    180195                        node->name,
    181196                        Type::StorageClasses( node->storage.val ),
    182197                        LinkageSpec::Spec( node->linkage.val ),
    183                         get<FunctionType>().accept1( node->type ),
     198                        ftype,
     199                        //get<FunctionType>().accept1( node->type ),
    184200                        {},
    185201                        get<Attribute>().acceptL( node->attributes ),
     
    11521168
    11531169        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
    11541173                auto ty = new FunctionType {
    11551174                        cv( node ),
    11561175                        (bool)node->isVarArgs
    11571176                };
    1158                 ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
    1159                 ty->parameters = get<DeclarationWithType>().acceptL( node->params );
     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 );
    11601194                ty->forall = get<TypeDecl>().acceptL( node->forall );
    11611195                return visitType( node, ty );
     
    13741408        ast::Node * node = nullptr;
    13751409        /// cache of nodes that might be referenced by readonly<> for de-duplication
    1376         std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
     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 = {};
    13771415
    13781416        // Local Utilities:
     
    14471485                auto it = cache.find( old );
    14481486                if ( it == cache.end() ) return false;
    1449                 node = it->second;
     1487                node = const_cast<ast::Node *>(it->second.get());
    14501488                return true;
    14511489        }
     
    14861524        virtual void visit( const FunctionDecl * old ) override final {
    14871525                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
    14881544                auto decl = new ast::FunctionDecl{
    14891545                        old->location,
    14901546                        old->name,
    1491                         GET_ACCEPT_1(type, FunctionType),
     1547                        // GET_ACCEPT_1(type, FunctionType),
     1548                        std::move(paramVars),
     1549                        std::move(returnVars),
    14921550                        {},
    14931551                        { old->storageClasses.val },
     
    14961554                        { old->get_funcSpec().val }
    14971555                };
     1556
     1557                decl->type = ftype;
    14981558                cache.emplace( old, decl );
     1559
    14991560                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
    15001561                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
     
    25152576                        cv( old )
    25162577                };
    2517                 ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
    2518                 ty->params = GET_ACCEPT_V( parameters, DeclWithType );
     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                }
    25192588                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
    25202589                visitType( old, ty );
  • src/AST/Decl.hpp

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

    r91fb850 rc7806122  
    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
    3545        /// Substitute parameter/return type
    3646        std::vector< ptr< DeclWithType > > operator() ( const std::vector< ptr< DeclWithType > > & o ) {
     
    4858                return n;
    4959        }
     60
     61        */
    5062};
    5163
  • src/AST/Pass.impl.hpp

    r91fb850 rc7806122  
    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
    467471                                maybe_accept( node, &FunctionDecl::type );
    468472                                // function body needs to have the same scope as parameters - CompoundStmt will not enter
  • src/AST/SymbolTable.cpp

    r91fb850 rc7806122  
    335335}
    336336
     337/*
    337338void SymbolTable::addFunctionType( const FunctionType * ftype ) {
    338339        addTypes( ftype->forall );
     
    340341        addIds( ftype->params );
    341342}
     343*/
    342344
    343345void SymbolTable::lazyInitScope() {
     
    368370                assert( ! params.empty() );
    369371                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    370                 const Type * base = InitTweak::getPointerBase( params.front()->get_type() );
     372                const Type * base = InitTweak::getPointerBase( params.front() );
    371373                assert( base );
    372374                return Mangle::mangle( base );
  • src/AST/SymbolTable.hpp

    r91fb850 rc7806122  
    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

    r91fb850 rc7806122  
    102102// --- FunctionType
    103103
     104
    104105FunctionType::FunctionType( const FunctionType & o )
    105106: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     
    112113
    113114namespace {
    114         bool containsTtype( const std::vector<ptr<DeclWithType>> & l ) {
     115        bool containsTtype( const std::vector<ptr<Type>> & l ) {
    115116                if ( ! l.empty() ) {
    116                         return Tuples::isTtype( l.back()->get_type() );
     117                        return Tuples::isTtype( l.back() );
    117118                }
    118119                return false;
  • src/AST/Type.hpp

    r91fb850 rc7806122  
    302302class FunctionType final : public ParameterizedType {
    303303public:
    304         std::vector<ptr<DeclWithType>> returns;
    305         std::vector<ptr<DeclWithType>> params;
     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;
    306309
    307310        /// Does the function accept a variable number of arguments following the arguments specified
  • src/InitTweak/InitTweak.cc

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

    r91fb850 rc7806122  
    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], paramType, symtab, cand->env, convCost ) );
    195                         convCost.decSpec( specCost( paramType ) );
     194                                        args[i], *param, symtab, cand->env, convCost ) );
     195                        convCost.decSpec( specCost( *param ) );
    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()->get_type();
     700                                const ast::Type * returnType = funcType->returns.front();
    701701                                if ( ! unify(
    702702                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     
    712712                        std::size_t genStart = 0;
    713713
    714                         for ( const ast::DeclWithType * param : funcType->params ) {
    715                                 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
     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 ) {
    716730                                // Try adding the arguments corresponding to the current parameter to the existing
    717731                                // matches
     732                                // no default args for indirect calls
    718733                                if ( ! instantiateArgument(
    719                                         obj->type, obj->init, args, results, genStart, symtab ) ) return;
    720                         }
    721 
     734                                        param, nullptr, args, results, genStart, symtab ) ) return;
     735                        }
     736
     737                        endMatch:
    722738                        if ( funcType->isVarArgs ) {
    723739                                // append any unused arguments to vararg pack
  • src/ResolvExpr/CurrentObject.cc

    r91fb850 rc7806122  
    594594        class SimpleIterator final : public MemberIterator {
    595595                CodeLocation location;
    596                 readonly< Type > type = nullptr;
     596                const 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                 readonly< ArrayType > array = nullptr;
    633                 readonly< Type > base = nullptr;
     632                const ArrayType * array = nullptr;
     633                const Type * base = nullptr;
    634634                size_t index = 0;
    635635                size_t size = 0;
  • src/ResolvExpr/Resolver.cc

    r91fb850 rc7806122  
    12231223                template<typename Iter>
    12241224                inline bool nextMutex( Iter & it, const Iter & end ) {
    1225                         while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
     1225                        while ( it != end && ! (*it)->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, paramType, resultEnv, need, have, open,
     1643                                                                                arg->expr->result, *param, resultEnv, need, have, open,
    16441644                                                                                symtab )
    16451645                                                                ) {
     
    16481648                                                                        ss << "candidate function not viable: no known conversion "
    16491649                                                                                "from '";
    1650                                                                         ast::print( ss, (*param)->get_type() );
     1650                                                                        ast::print( ss, *param );
    16511651                                                                        ss << "' to '";
    16521652                                                                        ast::print( ss, arg->expr->result );
  • src/ResolvExpr/SatisfyAssertions.cpp

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

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

    r91fb850 rc7806122  
    395395
    396396        template< typename Iterator1, typename Iterator2 >
    397         bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     397        bool unifyTypeList( 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 ( 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 ) ) {
     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 ) ) {
    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::DeclWithType > > flattenList(
    787                         const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
     786                static std::vector< ast::ptr< ast::Type > > flattenList(
     787                        const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
    788788                ) {
    789                         std::vector< ast::ptr< ast::DeclWithType > > dst;
     789                        std::vector< ast::ptr< ast::Type > > dst;
    790790                        dst.reserve( src.size() );
    791                         for ( const ast::DeclWithType * d : src ) {
     791                        for ( const auto & 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::DeclWithType> dc = d->accept(expander);
    796                                 auto types = flatten( dc->get_type() );
     795                                ast::ptr<ast::Type> dc = d->accept(expander);
     796                                auto types = flatten( dc );
    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( new ast::ObjectDecl{ dc->location, "", t } );
     805                                        dst.emplace_back( t );
    806806                                }
    807807                        }
     
    811811                /// Creates a tuple type based on a list of DeclWithType
    812812                template< typename Iter >
    813                 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
     813                static ast::ptr< ast::Type > tupleFromTypes( 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)->get_type(), types );
     818                                flatten( *crnt, types );
    819819
    820820                                ++crnt;
     
    825825
    826826                template< typename Iter >
    827                 static bool unifyDeclList(
     827                static bool unifyTypeList(
    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)->get_type();
    834                                 const ast::Type * t2 = (*crnt2)->get_type();
     833                                const ast::Type * t1 = *crnt1;
     834                                const ast::Type * t2 = *crnt2;
    835835                                bool isTuple1 = Tuples::isTtype( t1 );
    836836                                bool isTuple2 = Tuples::isTtype( t2 );
     
    840840                                        // combine remainder of list2, then unify
    841841                                        return unifyExact(
    842                                                 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     842                                                t1, tupleFromTypes( 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                                                 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     847                                                tupleFromTypes( 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)->get_type();
     862                                const ast::Type * t1 = *crnt1;
    863863                                if ( ! Tuples::isTtype( t1 ) ) return false;
    864864                                return unifyExact(
    865                                         t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     865                                        t1, tupleFromTypes( 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)->get_type();
     869                                const ast::Type * t2 = *crnt2;
    870870                                if ( ! Tuples::isTtype( t2 ) ) return false;
    871871                                return unifyExact(
    872                                         tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     872                                        tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    873873                                        noWiden(), symtab );
    874874                        }
     
    877877                }
    878878
    879                 static bool unifyDeclList(
    880                         const std::vector< ast::ptr< ast::DeclWithType > > & list1,
    881                         const std::vector< ast::ptr< ast::DeclWithType > > & list2,
     879                static bool unifyTypeList(
     880                        const std::vector< ast::ptr< ast::Type > > & list1,
     881                        const std::vector< ast::ptr< ast::Type > > & list2,
    882882                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    883883                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    884884                ) {
    885                         return unifyDeclList(
     885                        return unifyTypeList(
    886886                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    887887                                symtab );
     
    928928                        ) return;
    929929
    930                         if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
    931                         if ( ! unifyDeclList(
     930                        if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
     931                        if ( ! unifyTypeList(
    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]->get_type();
     1234                if ( func->returns.size() == 1 ) return func->returns[0];
    12351235
    12361236                std::vector<ast::ptr<ast::Type>> tys;
    1237                 for ( const ast::DeclWithType * decl : func->returns ) {
    1238                         tys.emplace_back( decl->get_type() );
     1237                for ( const auto & decl : func->returns ) {
     1238                        tys.emplace_back( decl );
    12391239                }
    12401240                return new ast::TupleType{ std::move(tys) };
  • src/SymTab/Mangler.cc

    r91fb850 rc7806122  
    551551                        GuardValue( inFunctionType );
    552552                        inFunctionType = true;
    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 );
     553                        if (functionType->returns.empty()) mangleName << Encoding::void_t;
     554                        else accept_each( functionType->returns, *visitor );
    556555                        mangleName << "_";
    557                         std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
    558                         accept_each( paramTypes, *visitor );
     556                        accept_each( functionType->params, *visitor );
    559557                        mangleName << "_";
    560558                }
  • src/SymTab/Validate.cc

    r91fb850 rc7806122  
    13841384        /// Replaces enum types by int, and function/array types in function parameter and return
    13851385        /// lists by appropriate pointers
     1386        /*
    13861387        struct EnumAndPointerDecay_new {
    13871388                const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
     
    14341435                }
    14351436        };
     1437        */
    14361438
    14371439        /// expand assertions from a trait instance, performing appropriate type variable substitutions
     
    18371839const ast::Type * validateType(
    18381840                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    1839         ast::Pass< EnumAndPointerDecay_new > epc;
     1841        // ast::Pass< EnumAndPointerDecay_new > epc;
    18401842        ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    18411843        ast::Pass< ForallPointerDecay_new > fpd{ loc };
    18421844
    1843         return type->accept( epc )->accept( lrt )->accept( fpd );
     1845        return type->accept( lrt )->accept( fpd );
    18441846}
    18451847
Note: See TracChangeset for help on using the changeset viewer.