Changes in / [c7806122:91fb850]
- Files:
-
- 3 deleted
- 23 edited
-
doc/LaTeXmacros/common.tex (modified) (4 diffs)
-
doc/LaTeXmacros/lstlang.sty (modified) (3 diffs)
-
doc/proposals/function_type_change.md (deleted)
-
doc/refrat/refrat.tex (modified) (3 diffs)
-
doc/theses/andrew_beach_MMath/glossaries.tex (deleted)
-
doc/theses/andrew_beach_MMath/thesis.tex (modified) (1 diff)
-
doc/theses/fangren_yu_COOP_S20/Report.tex (modified) (9 diffs)
-
doc/theses/fangren_yu_COOP_S20/cfa_developer_reference.pdf (deleted)
-
doc/user/user.tex (modified) (17 diffs)
-
src/AST/Convert.cpp (modified) (7 diffs)
-
src/AST/Decl.hpp (modified) (1 diff)
-
src/AST/ForallSubstitutor.hpp (modified) (2 diffs)
-
src/AST/Pass.impl.hpp (modified) (1 diff)
-
src/AST/SymbolTable.cpp (modified) (3 diffs)
-
src/AST/SymbolTable.hpp (modified) (1 diff)
-
src/AST/Type.cpp (modified) (2 diffs)
-
src/AST/Type.hpp (modified) (1 diff)
-
src/InitTweak/InitTweak.cc (modified) (1 diff)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (3 diffs)
-
src/ResolvExpr/CurrentObject.cc (modified) (2 diffs)
-
src/ResolvExpr/Resolver.cc (modified) (3 diffs)
-
src/ResolvExpr/SatisfyAssertions.cpp (modified) (1 diff)
-
src/ResolvExpr/SpecCost.cc (modified) (1 diff)
-
src/ResolvExpr/Unify.cc (modified) (12 diffs)
-
src/SymTab/Mangler.cc (modified) (1 diff)
-
src/SymTab/Validate.cc (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/LaTeXmacros/common.tex
rc7806122 r91fb850 11 11 %% Created On : Sat Apr 9 10:06:17 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Wed Sep 23 21:21:55202014 %% Update Count : 45413 %% Last Modified On : Fri Sep 4 13:56:52 2020 14 %% Update Count : 383 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 55 55 \newlength{\parindentlnth} 56 56 \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}} 57 72 58 73 \usepackage{pslatex} % reduce size of san serif font … … 229 244 \usepackage{listings} % format program code 230 245 \usepackage{lstlang} 231 \makeatletter232 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 correctly238 \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 lstinline245 %\usepackage{etoolbox}246 %\patchcmd{\lsthk@TextStyle}{\let\lst@DefEsc\@empty}{}{}{\errmessage{failed to patch}}247 248 % allow adding to lst literate249 \def\addToLiterate#1{\protect\edef\lst@literate{\unexpanded\expandafter{\lst@literate}\unexpanded{#1}}}250 \lst@Key{add to literate}{}{\addToLiterate{#1}}251 \makeatother252 246 253 247 \newcommand{\CFADefaults}{% … … 268 262 belowskip=3pt, 269 263 % replace/adjust listing characters that look bad in sanserif 270 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0. 75ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1264 literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}1 271 265 {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1 272 266 {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex\textgreater}2, 273 }% lstset 274 }% CFADefaults 275 276 \ifdefined\CFALatin% 277 \lstnewenvironment{cfa}[1][]{\CFADefaults 278 \lstset{ 279 language=CFA, 280 moredelim=**[is][\color{red}]{®}{®}, % red highlighting ®...® (registered trademark symbol) emacs: C-q M-. 267 moredelim=**[is][\color{red}]{?}{?}, % red highlighting ?...? (registered trademark symbol) emacs: C-q M-. 281 268 moredelim=**[is][\color{blue}]{ß}{ß}, % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_ 282 269 moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-" 283 270 moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ 284 % replace/adjust listing characters that look bad in sanserif285 add to literate={`}{\ttfamily\upshape\hspace*{-0.1ex}`}1286 271 }% lstset 287 \lstset{#1} 288 }{} 272 }% CFADefaults 273 \newcommand{\CFAStyle}{% 274 \CFADefaults 289 275 % inline code ©...© (copyright symbol) emacs: C-q M-) 290 276 \lstMakeShortInline© % single-character for \lstinline 291 \else% extra Latin-1 escape characters 292 \lstset{ 293 language=CFA, 294 escapechar=\$, % LaTeX escape in CFA code 295 moredelim=**[is][\color{red}]{@}{@}, % red highlighting `...` (backtick symbol) 296 }% lstset 297 \lstnewenvironment{cfa}[1][]{\CFADefaults 298 \lstset{ 299 language=CFA, 300 escapechar=\$, % LaTeX escape in CFA code 301 moredelim=**[is][\color{red}]{@}{@}, % red highlighting `...` (backtick symbol) 302 }% lstset 303 \lstset{#1} 304 }{} 305 % inline code @...@ (at symbol) 306 \lstMakeShortInline@ % single-character for \lstinline 307 \fi% 277 }% CFAStyle 278 279 \lstnewenvironment{cfa}[1][] 280 {\CFADefaults\lstset{#1}} 281 {} 308 282 309 283 % Local Variables: % -
doc/LaTeXmacros/lstlang.sty
rc7806122 r91fb850 8 8 %% Created On : Sat May 13 16:34:42 2017 9 9 %% Last Modified By : Peter A. Buhr 10 %% Last Modified On : Wed Sep 23 22:40:04 202011 %% Update Count : 2 410 %% Last Modified On : Tue Jan 8 14:40:33 2019 11 %% Update Count : 21 12 12 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 13 … … 115 115 auto, _Bool, catch, catchResume, choose, _Complex, __complex, __complex__, __const, __const__, 116 116 coroutine, disable, dtype, enable, exception, __extension__, fallthrough, fallthru, finally, 117 __float80, float80, __float128, float128, forall, ftype, generator,_Generic, _Imaginary, __imag, __imag__,117 __float80, float80, __float128, float128, forall, ftype, _Generic, _Imaginary, __imag, __imag__, 118 118 inline, __inline, __inline__, __int128, int128, __label__, monitor, mutex, _Noreturn, one_t, or, 119 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, suspend,thread,119 otype, restrict, __restrict, __restrict__, __signed, __signed__, _Static_assert, thread, 120 120 _Thread_local, throw, throwResume, timeout, trait, try, ttype, typeof, __typeof, __typeof__, 121 121 virtual, __volatile, __volatile__, waitfor, when, with, zero_t, … … 125 125 126 126 % C++ programming language 127 \lstdefinelanguage{C++}[ANSI]{C++}{ 128 morekeywords={nullptr,} 129 } 127 \lstdefinelanguage{C++}[ANSI]{C++}{} 130 128 131 129 % uC++ programming language, based on ANSI C++ -
doc/refrat/refrat.tex
rc7806122 r91fb850 11 11 %% Created On : Wed Apr 6 14:52:25 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Thu Sep 24 16:34:51 202014 %% Update Count : 10 913 %% Last Modified On : Wed Jan 31 17:30:23 2018 14 %% Update Count : 108 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 30 30 \usepackage{upquote} % switch curled `'" to straight 31 31 \usepackage{calc} 32 \usepackage{xspace} 32 33 \usepackage{varioref} % extended references 34 \usepackage{listings} % format program code 33 35 \usepackage[flushmargin]{footmisc} % support label/reference in footnote 34 36 \usepackage{latexsym} % \Box glyph 35 37 \usepackage{mathptmx} % better math font with "times" 36 38 \usepackage[usenames]{color} 37 \newcommand{\CFALatin}{} 39 \input{common} % common CFA document macros 40 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref} 41 \usepackage{breakurl} 42 \renewcommand{\UrlFont}{\small\sf} 43 44 \usepackage[pagewise]{lineno} 45 \renewcommand{\linenumberfont}{\scriptsize\sffamily} 46 \usepackage[firstpage]{draftwatermark} 47 \SetWatermarkLightness{0.9} 48 49 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore 50 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR 51 % AFTER HYPERREF. 52 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 53 54 \setlength{\topmargin}{-0.45in} % move running title into header 55 \setlength{\headsep}{0.25in} 56 57 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 59 \CFAStyle % use default CFA format-style 60 \lstnewenvironment{C++}[1][] % use C++ style 61 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®}#1}} 62 {} 63 38 64 % inline code ©...© (copyright symbol) emacs: C-q M-) 39 65 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-. … … 43 69 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ 44 70 % math escape $...$ (dollar symbol) 45 \input{common} % common CFA document macros46 \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 underscore56 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR57 % AFTER HYPERREF.58 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}59 60 \setlength{\topmargin}{-0.45in} % move running title into header61 \setlength{\headsep}{0.25in}62 71 63 72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 64 73 65 \CFADefaults % use default CFA format-style66 \lstnewenvironment{C++}[1][] % use C++ style67 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}68 {}69 70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%71 72 74 % Names used in the document. 73 \newcommand{\Version}{\input{ build/version}}75 \newcommand{\Version}{\input{../../version}} 74 76 \newcommand{\Textbf}[2][red]{{\color{#1}{\textbf{#2}}}} 75 77 \newcommand{\Emph}[2][red]{{\color{#1}\textbf{\emph{#2}}}} -
doc/theses/andrew_beach_MMath/thesis.tex
rc7806122 r91fb850 34 34 \usepackage[toc,abbreviations]{glossaries-extra} 35 35 36 % Define all the glossaries. 37 \input{glossaries} 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 } 38 69 39 70 % Generate the glossaries defined above. -
doc/theses/fangren_yu_COOP_S20/Report.tex
rc7806122 r91fb850 26 26 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 27 27 \newcommand{\NOTE}{\textbf{NOTE}} 28 \newcommand{\TODO}[1]{{\color{Purple}#1}}29 28 30 29 \setlength{\topmargin}{-0.45in} % move running title into header … … 36 35 \lstset{ 37 36 language=C++, % make C++ the default language 37 escapechar=\$, % LaTeX escape in CFA code 38 moredelim=**[is][\color{red}]{`}{`}, 38 39 }% lstset 40 \lstMakeShortInline@% 39 41 \lstnewenvironment{C++}[1][] % use C++ style 40 {\lstset{language=C++,moredelim=**[is][\color{red}]{@}{@},#1}}{} 42 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{`}{`},#1}} 43 {} 41 44 42 45 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 81 84 \section{Overview} 82 85 83 cfa-cc is the reference compiler for the \CFA programming language, which is a non-object-oriented extension to C. 84 \CFA attempts to introduce productive modern programming language features to C while maintaining as much backward-compatibility as possible, so that most existing C programs can seamlessly work with \CFA. 85 86 Since the \CFA project dates back to the early 2000s, and only restarted in the past few years, there is a significant amount of legacy code in the current compiler codebase with little documentation. 87 The lack of documentation makes it difficult to develop new features from the current implementation and diagnose problems. 88 89 Currently, the \CFA team is also facing poor compiler performance. 90 For the development of a new programming language, writing standard libraries is an important component. 91 The slow compiler causes building of the library files to take tens of minutes, making iterative development and testing almost impossible. 92 There is an ongoing effort to rewrite the core data-structure of the compiler to overcome the performance issue, but many bugs have appeared during this work, and lack of documentation is hampering debugging. 93 94 This developer's reference manual begins the documentation and should be continuously im\-proved until it eventually covers the entire compiler codebase. 95 For now, the focus is mainly on the parts being rewritten, and also the primary performance bottleneck, namely the resolution algorithm. 96 Its aimed is to provide new project developers with guidance in understanding the codebase, and clarify the purpose and behaviour of certain functions that are not mentioned in the previous \CFA research papers~\cite{Bilson03,Ditchfield92,Moss19}. 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. 97 111 98 112 99 113 \section{Compiler Framework} 100 114 101 \CFA source code is first transformed into an abstract syntax tree (AST) by the parser before analyzed by the compiler.102 103 104 115 \subsection{AST Representation} 105 116 106 107 There are 4 major categories of AST nodes used by the compiler, along with some derived structures. 108 109 \subsubsection{Declaration Nodes} 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} 110 124 111 125 A declaration node represents either of: 112 126 \begin{itemize} 113 127 \item 114 type declaration: @struct@, @union@, @typedef@ or type parameter \TODO{(see Appendix A.3)} 115 \item 116 variable declaration117 \item 118 function declaration128 Type declaration: struct, union, typedef or type parameter (see Appendix A.3) 129 \item 130 Variable declaration 131 \item 132 Function declaration 119 133 \end{itemize} 120 134 Declarations are introduced by standard C declarations, with the usual scoping rules. 121 In addition, declarations can also be qualified by the \lstinline[language=CFA]@forall@ clause (which is the origin of \CFA's name): 135 In addition, declarations can also be introduced by the forall clause (which is the origin 136 of \CFA's name): 122 137 \begin{cfa} 123 forall ( <$\emph{TypeParameterList}$> | <$\emph{AssertionList}$>)138 forall (<$\emph{TypeParameterList}$> | <$\emph{AssertionList}$>) 124 139 $\emph{declaration}$ 125 140 \end{cfa} 126 Type parameters in \CFA are similar to \CC template type parameters. 127 The \CFAdeclaration141 Type parameters in \CFA are similar to \CC template type parameters. The \CFA 142 declaration 128 143 \begin{cfa} 129 144 forall (dtype T) ... 130 145 \end{cfa} 131 behaves similarly tothe \CC template declaration146 behaves similarly as the \CC template declaration 132 147 \begin{C++} 133 148 template <typename T> ... 134 149 \end{C++} 135 150 136 Assertions are a distinctive feature of \CFA, similar to \emph{interfaces} in D and Go, and \emph{traits} in Rust. 137 Contrary to the \CC template where arbitrary functions and operators can be used in a template definition, in a \CFA parametric function, operations on parameterized types must be declared in assertions. 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 138 155 Consider the following \CC template: 139 156 \begin{C++} 140 @template@ forall<typename T> T foo( T t) {141 return t + t * t;157 template <typename T> int foo(T t) { 158 return bar(t) + baz(t); 142 159 } 143 160 \end{C++} 144 where there are no explicit requirements on the type @T@. 145 Therefore, the \CC compiler must deduce what operators are required during textual (macro) expansion of the template at each usage. 146 As a result, templates cannot be compiled. 147 \CFA assertions specify restrictions on type parameters: 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: 148 163 \begin{cfa} 149 forall ( dtype T | @{ T ?+?( T, T ); T ?*?( T, T ) }@ ) int foo ( T t) {150 return t + t * t;164 forall (dtype T | { int bar(T); int baz(t); }) int foo (T t) { 165 return bar(t) + baz(t); 151 166 } 152 167 \end{cfa} 153 Assertions are written using the usual \CFA function declaration syntax. 154 Only types with operators ``@+@'' and ``@*@'' work with this function, and the function prototype is sufficient to allow separate compilation. 155 156 Type parameters and assertions are used in the following compiler data-structures. 157 158 159 \subsubsection{Type Nodes} 160 161 Type nodes represent the type of an object or expression. 162 Named types reference the corresponding type declarations. 163 The type of a function is its function pointer type (same as standard C). 164 With the addition of type parameters, named types may contain a list of parameter values (actual parameter types). 165 166 167 \subsubsection{Statement Nodes} 168 169 Statement nodes represent the executable statements in the program, including basic expression statements, control flows and blocks. 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. 170 183 Local declarations (within a block statement) are represented as declaration statements. 171 184 172 173 \subsubsection{Expression Nodes} 174 175 Some expressions are represented differently before and after the resolutionstage:185 \subsubsection{Expression nodes} 186 187 Some expressions are represented differently in the compiler before and after resolution 188 stage: 176 189 \begin{itemize} 177 190 \item 178 Name expressions: @NameExpr@ pre-resolution, @VariableExpr@ post-resolution 179 \item 180 Member expressions: @UntypedMemberExpr@ pre-resolution, @MemberExpr@ post-resolution 181 \item 182 \begin{sloppypar} 183 Function call expressions (including overloadable operators): @UntypedExpr@ pre-resolution, @ApplicationExpr@ post-resolution 184 \end{sloppypar} 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 185 196 \end{itemize} 186 The pre-resolution representation contains only the symbols.187 Post-resolution linksthem to the actual variable and function declarations.197 The pre-resolution representations contain only the symbols. Post-resolution results link 198 them to the actual variable and function declarations. 188 199 189 200 190 201 \subsection{Compilation Passes} 191 202 192 Compilation steps are implemented as passes, which follows a general structural recursion pattern on the syntax tree. 193 194 The basic workflow of compilation passes follows preorder and postorder traversal on the AST data-structure, implemented with visitor pattern, and can be loosely described with the following pseudocode: 195 \begin{C++} 196 Pass::visit( node_t node ) { 197 previsit( node ); 198 if ( visit_children ) 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) 199 213 for each child of node: 200 child.accept( this);201 postvisit( node);214 child.accept(this); 215 postvisit(node); 202 216 } 203 217 \end{C++} 204 Operations in @previsit@ happen in preorder (top to bottom) and operations in @postvisit@ happen in postorder (bottom to top). 205 The precise order of recursive operations on child nodes can be found in @Common/PassVisitor.impl.h@ (old) and @AST/Pass.impl.hpp@ (new). 206 207 Implementations of compilation passes follow certain conventions: 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: 208 223 \begin{itemize} 209 224 \item 210 Passes \textbf{should not} directly override the visit method (Non-virtual Interface principle); 211 if a pass desires different recursion behaviour, it should set @visit_children@ to false and perform recursive calls manually within previsit or postvisit procedures. 212 To enable this option, inherit from the @WithShortCircuiting@ mixin. 213 \item 214 previsit may mutate the node but \textbf{must not} change the node type or return @nullptr@. 215 \item 216 postvisit may mutate the node, reconstruct it to a different node type, or delete it by returning @nullptr@. 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. 217 234 \item 218 235 If the previsit or postvisit method is not defined for a node type, the step is skipped. 219 If the return type is declared as @void@, the original node is returned by default.220 These behaviours are controlled by template specialization rules; 221 see @Common/PassVisitor.proto.h@ (old) and @AST/@ @Pass.proto.hpp@ (new) for details.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. 222 239 \end{itemize} 223 240 Other useful mixin classes for compilation passes include: 224 241 \begin{itemize} 225 242 \item 226 @WithGuards@ allows saving and restoring variable values automatically upon entering/exiting the current node. 227 \item 228 @WithVisitorRef@ creates a wrapped entity for the current pass (the actual argument passed to recursive calls internally) for explicit recursion, usually used together with @WithShortCircuiting@. 229 \item 230 @WithSymbolTable@ gives a managed symbol table with built-in scoping-rule handling (\eg on entering and exiting a block statement) 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) 231 252 \end{itemize} 232 \NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading resolution rules, it \textbf{must} explicitly introduce the inherited previsit and postvisit procedures to its own scope, or otherwise they are not picked up by template resolution: 253 \NOTE: If a pass extends the functionality of another existing pass, due to \CC overloading 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: 233 256 \begin{C++} 234 257 class Pass2: public Pass1 { 235 @using Pass1::previsit;@236 @using Pass1::postvisit;@258 using Pass1::previsit; 259 using Pass1::postvisit; 237 260 // new procedures 238 261 } … … 240 263 241 264 242 \subsection{Data Structure Change (new-ast)} 243 244 It has been observed that excessive copying of syntax tree structures accounts for a majority of computation cost and significantly slows down the compiler. 245 In the previous implementation of the syntax tree, every internal node has a unique parent; 246 therefore all copies are required to duplicate the entire subtree. 247 A new, experimental re-implementation of the syntax tree (source under directory @AST/@ hereby referred to as ``new-ast'') attempts to overcome this issue with a functional approach that allows sharing of common sub-structures and only makes copies when necessary. 248 249 The core of new-ast is a customized implementation of smart pointers, similar to @std::shared_ptr@ and @std::weak_ptr@ in the \CC standard library. 250 Reference counting is used to detect sharing and allowing certain optimizations. 251 For a purely functional (immutable) data-structure, all mutations are modelled by shallow copies along the path of mutation. 265 \subsection{Data Structure Change WIP (new-ast)} 266 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. 252 279 With reference counting optimization, unique nodes are allowed to be mutated in place. 253 This however, may potentially introduce some complications and bugs; 254 a few issues are discussed near the end of this section. 255 256 257 \subsubsection{Source: \lstinline{AST/Node.hpp}} 258 259 Class @ast::Node@ is the base class of all new-ast node classes, which implements reference counting mechanism. 260 Two different counters are recorded: ``strong'' reference count for number of nodes semantically owning it; 261 ``weak'' reference count for number of nodes holding a mere reference and only need to observe changes. 262 Class @ast::ptr_base@ is the smart pointer implementation and also takes care of resource management. 263 264 Direct access through the smart pointer is read-only. 265 A mutable access should be obtained by calling @shallowCopy@ or mutate as below. 266 267 Currently, the weak pointers are only used to reference declaration nodes from a named type, or a variable expression. 268 Since declaration nodes are intended to denote unique entities in the program, weak pointers always point to unique (unshared) nodes. 269 This property may change in the future, and weak references to shared nodes may introduce some problems; 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; 270 299 see mutate function below. 271 300 272 All node classes should always use smart pointers in structure definitions versus raw pointers. 273 Function 301 All node classes should always use smart pointers in the structure and should not use raw 302 pointers. 303 274 304 \begin{C++} 275 305 void ast::Node::increment(ref_type ref) 276 306 \end{C++} 277 increments this node's strong or weak reference count. 278 Function 307 Increments this node's strong or weak reference count. 279 308 \begin{C++} 280 309 void ast::Node::decrement(ref_type ref, bool do_delete = true) 281 310 \end{C++} 282 decrements this node's strong or weak reference count. 283 If strong reference count reaches zero, the node is deleted. 284 \NOTE: Setting @do_delete@ to false may result in a detached node. 285 Subsequent code should manually delete the node or assign it to a strong pointer to prevent memory leak. 286 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. 287 315 Reference counting functions are internally called by @ast::ptr_base@. 288 Function289 316 \begin{C++} 290 317 template<typename node_t> 291 318 node_t * shallowCopy(const node_t * node) 292 319 \end{C++} 293 returns a mutable, shallow copy of node: all child pointers are pointing to the same child nodes. 294 Function 320 Returns a mutable, shallow copy of node: all child pointers are pointing to the same child 321 nodes. 295 322 \begin{C++} 296 323 template<typename node_t> 297 324 node_t * mutate(const node_t * node) 298 325 \end{C++} 299 returns a mutable pointer to the same node, if the node is unique (strong reference count is 1); 300 otherwise, it returns @shallowCopy(node)@. 301 It is an error to mutate a shared node that is weak-referenced. 302 Currently this does not happen. 303 A problem may appear once weak pointers to shared nodes (\eg expression nodes) are used; 304 special care is needed. 305 306 \NOTE: This naive uniqueness check may not be sufficient in some cases. 307 A discussion of the issue is presented at the end of this section. 308 Functions 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. 309 334 \begin{C++} 310 335 template<typename node_t, typename parent_t, typename field_t, typename assn_t> 311 const node_t * mutate_field(const node_t * node, field_t parent_t::* field, assn_t && val)336 const node_t * mutate_field(const node_t * node, field_t parent_t::*field, assn_t && val) 312 337 \end{C++} 313 338 \begin{C++} … … 317 342 field_t && val) 318 343 \end{C++} 319 are helpers for mutating a field on a node using pointer to a member function (creates shallow copy when necessary). 320 321 322 \subsubsection{Issue: Undetected Sharing}323 324 The @mutate@ behavio ur described above has a problem: deeper shared nodes may be344 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 325 350 mistakenly considered as unique. \VRef[Figure]{f:DeepNodeSharing} shows how the problem could arise: 326 351 \begin{figure} … … 330 355 \label{f:DeepNodeSharing} 331 356 \end{figure} 332 Given the tree rooted at P1, which is logically the chain P1-A-B, and P2 is irrelevant, assume @mutate(B)@ is called. 333 The algorithm considers B as unique since it is only directly owned by A. 334 However, the other tree P2-A-B indirectly shares the node B and is therefore wrongly mutated. 335 336 To partly address this problem, if the mutation is called higher up the tree, a chain mutation helper can be used. 337 338 \subsubsection{Source: \lstinline{AST/Chain.hpp}} 339 340 Function 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 341 368 \begin{C++} 342 369 template<typename node_t, Node::ref_type ref_t> 343 370 auto chain_mutate(ptr_base<node_t, ref_t> & base) 344 371 \end{C++} 345 returns a chain mutator handle that takes pointer-to-member to go down the tree, while creating shallow copies as necessary; 346 see @struct _chain_mutator@ in the source code for details. 347 348 For example, in the above diagram, if mutation of B is wanted while at P1, the call using @chain_mutate@ looks like the following: 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: 349 378 \begin{C++} 350 379 chain_mutate(P1.a)(&A.b) = new_value_of_b; 351 380 \end{C++} 352 \NOTE: if some node in chain mutate is shared (therefore shallow copied), it implies that every node further down is also copied, thus correctly executing the functional mutation algorithm. 353 This example code creates copies of both A and B and performs mutation on the new nodes, so that the other tree P2-A-B is untouched. 354 However, if a pass traverses down to node B and performs mutation, for example, in @postvisit(B)@, information on sharing higher up is lost. 355 Since the new-ast structure is only in experimental use with the resolver algorithm, which mostly rebuilds the tree bottom-up, this issue does not actually happen. 356 It should be addressed in the future when other compilation passes are migrated to new-ast and many of them contain procedural mutations, where it might cause accidental mutations to other logically independent trees (\eg common sub-expression) and become a bug. 357 358 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 ??? 359 395 \section{Compiler Algorithm Documentation} 360 396 361 This compiler algorithm documentation covers most of the resolver, data structures used in variable and expression resolution, and a few directly related passes. 362 Later passes involving code generation are not included yet; 363 documentation for those will be done latter. 364 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. 365 400 366 401 \subsection{Symbol Table} 367 402 368 \NOTE: For historical reasons, the symbol-table data-structure is called @indexer@ in the old implementation. 369 Hereby, the name is changed to @SymbolTable@. 370 The symbol table stores a mapping from names to declarations, implements a similar name-space separation rule, and provides the same scoping rules as standard C.\footnote{ISO/IEC 9899:1999, Sections 6.2.1 and 6.2.3.} 371 The difference in name-space rule is that @typedef@ aliases are no longer considered ordinary identifiers. 372 In addition to C tag-types (@struct@, @union@, @enum@), \CFA introduces another tag type, @trait@, which is a named collection of assertions. 373 374 375 \subsubsection{Source: \lstinline{AST/SymbolTable.hpp}} 376 377 \TODO{Add something here} 378 379 380 \subsubsection{Source: \lstinline{SymTab/Indexer.h}} 381 382 Function 403 \NOTE: For historical reasons, the symbol table data structure was called ``indexer'' in the 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 383 415 \begin{C++} 384 416 SymbolTable::addId(const DeclWithType * decl) 385 417 \end{C++} 386 provides name mangling of identifiers, since \CFA allows overloading of variables and functions. 387 The mangling scheme is closely based on the Itanium \CC ABI,\footnote{\url{https://itanium-cxx-abi.github.io/cxx-abi/abi.html}, Section 5.1} while making adaptations to \CFA specific features, mainly assertions and overloaded variables by type. 388 389 Naming conflicts are handled by mangled names; 390 lookup by name returns a list of declarations with the sameidentifier name.391 Functions 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 392 424 \begin{C++} 393 425 SymbolTable::addStruct(const StructDecl * decl) … … 396 428 SymbolTable::addTrait(const TraitDecl * decl) 397 429 \end{C++} 398 add a tag-type declaration to the symbol table. 399 Function 430 Adds a tag type declaration to the symbol table. 400 431 \begin{C++} 401 432 SymbolTable::addType(const NamedTypeDecl * decl) 402 433 \end{C++} 403 adds a @typedef@ alias to the symbol table. 404 405 \textbf{C Incompatibility Note}: Since \CFA allows using @struct@, @union@ and @enum@ type-names without a prefix keyword, as in \CC, @typedef@ names and tag-type names cannot be disambiguated by syntax rules. 406 Currently the compiler puts them together and disallows collision. 407 The following program is valid C but invalid \CFA (and \CC): 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: 408 440 \begin{C++} 409 441 struct A {}; 410 typedef int A; // gcc: ok, cfa: Cannot redefine typedef A411 struct A sa; // C disambiguates via struct prefix412 A ia;413 \end{C++}414 In practices, such usage is extremely rare, and hence, this change (as in \CC) has minimal impact on existing C programs.415 The declaration416 \begin{C++}417 struct A {};418 typedef struct A A; // A is an alias for struct A419 A a;420 struct A b;421 \end{C++}422 is not an error because the alias name is identical to the original.423 Finally, the following program is allowed in \CFA:424 \begin{C++}425 442 typedef int A; 426 void A(); // name mangled 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(); 427 452 // gcc: A redeclared as different kind of symbol, cfa: ok 428 453 \end{C++} 429 because the function name is mangled.430 431 454 432 455 \subsection{Type Environment and Unification} 433 456 434 The following core ideas underlie the parametric type-resolution algorithm. 435 A type environment organizes type parameters into \textbf{equivalent classes} and maps them to actual types. 436 Unification is the algorithm that takes two (possibly parametric) types and parameter mappings, and attempts to produce a common type by matching information in the type environments. 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. 437 462 438 463 The unification algorithm is recursive in nature and runs in two different modes internally: 439 464 \begin{itemize} 440 465 \item 441 Exact unification mode requires equivalent parameters to match perfectly. 442 \item 443 Inexact unification mode allows equivalent parameters to be converted to a common type. 466 \textbf{Exact} unification mode requires equivalent parameters to match perfectly; 467 \item 468 \textbf{Inexact} unification mode allows equivalent parameters to be converted to a 469 common type. 444 470 \end{itemize} 445 For a pair of matching parameters (actually, their equivalent classes), if either side is open (not bound to a concrete type yet), they are combined. 446 447 Within the inexact mode, types are allowed to differ on their cv-qualifiers (\eg @const@, @volatile@, \etc); 448 additionally, if a type never appear either in a parameter list or as the base type of a pointer, it may also be widened (\ie safely converted). 449 As \CFA currently does not implement subclassing as in object-oriented languages, widening conversions are only on the primitive types, \eg conversion from @int@ to @long int@. 450 451 The need for two unification modes comes from the fact that parametric types are considered compatible only if all parameters are exactly the same (not just compatible). 452 Pointer types also behaves similarly; 453 in fact, they may be viewed as a primitive kind of parametric types. 454 @int *@ and @long *@ are different types, just like @vector(int)@ and @vector(long)@ are, for the parametric type @*(T)@ / @vector(T)@, respectively. 455 456 The resolver uses the following @public@ functions:\footnote{ 457 Actual code also tracks assertions on type parameters; those extra arguments are omitted here for conciseness.} 458 459 460 \subsubsection{Source: \lstinline{ResolvExpr/Unify.cc}} 461 462 Function 463 \begin{C++} 464 bool unify(const Type * type1, const Type * type2, TypeEnvironment & env, 465 OpenVarSet & openVars, const SymbolTable & symtab, Type *& commonType) 466 \end{C++} 467 returns a boolean indicating if the unification succeeds or fails after attempting to unify @type1@ and @type2@ within current type environment. 468 If the unify succeeds, @env@ is modified by combining the equivalence classes of matching parameters in @type1@ and @type2@, and their common type is written to @commonType@. 469 If the unify fails, nothing changes. 470 Functions 471 \begin{C++} 472 bool typesCompatible(const Type * type1, const Type * type2, const SymbolTable & symtab, 473 const TypeEnvironment & env) 474 bool typesCompatibleIgnoreQualifiers(const Type * type1, const Type * type2, 475 const SymbolTable & symtab, const TypeEnvironment & env) 476 \end{C++} 477 return a boolean indicating if types @type1@ and @type2@ can possibly be the same type. 478 The second version ignores the outermost cv-qualifiers if present.\footnote{ 479 In \lstinline@const int * const@, only the second \lstinline@const@ is ignored.} 480 These function have no side effects. 481 482 \NOTE: No attempt is made to widen the types (exact unification is used), although the function names may suggest otherwise, \eg @typesCompatible(int, long)@ returns false. 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. 483 518 484 519 485 520 \subsection{Expression Resolution} 486 521 487 The design of the current version of expression resolver is outlined in the Ph.D.\ thesis by Aaron Moss~\cite{Moss19}. 522 The design of the current version of expression resolver is outlined in the Ph.D. Thesis from 523 Aaron Moss~\cite{Moss19}. 524 488 525 A summary of the resolver algorithm for each expression type is presented below. 489 526 490 All overloadable operators are modelled as function calls. 491 For a function call, interpretations of the function and arguments are found recursively. 492 Then the followingsteps produce a filtered list of valid interpretations: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: 493 530 \begin{enumerate} 494 531 \item 495 From all possible combinations of interpretations of the function and arguments, those where argument types may be converted to function parameter types are considered valid. 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. 496 535 \item 497 536 Valid interpretations with the minimum sum of argument costs are kept. 498 537 \item 499 \label{p:argcost} 500 Argument costs are then discarded; the actual cost for the function call expression is the sum of conversion costs from the argument types to parameter types. 501 \item 502 \label{p:returntype} 503 For each return type, the interpretations with satisfiable assertions are then sorted by actual cost computed in step~\ref{p:argcost}. 504 If for a given type, the minimum cost interpretations are not unique, that return type is ambiguous. 505 If the minimum cost interpretation is unique but contains an ambiguous argument, it is also ambiguous. 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. 506 546 \end{enumerate} 507 Therefore, for each return type, the resolver produces :547 Therefore, for each return type, the resolver produces either of: 508 548 \begin{itemize} 509 549 \item 510 no alternatives511 \item 512 asingle valid alternative513 \item 514 an ambiguous alternative550 No alternatives 551 \item 552 A single valid alternative 553 \item 554 An ambiguous alternative 515 555 \end{itemize} 516 \NOTE: an ambiguous alternative may be discarded at the parent expressions because a different return type matches better for the parent expressions. 517 518 The \emph{non}-overloadable expressions in \CFA are: cast expressions, address-of (unary @&@) expressions, short-circuiting logical expressions (@&&@, @||@) and ternary conditional expression (@?:@). 519 520 For a cast expression, the convertible argument types are kept. 521 Then the result is selected by lowest argument cost, and further by lowest conversion cost to target type. 522 If the lowest cost is still not unique or an ambiguous argument interpretation is selected, the cast expression is ambiguous. 523 In an expression statement, the top level expression is implicitly cast to @void@. 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. 524 568 525 569 For an address-of expression, only lvalue results are kept and the minimum cost is selected. 526 570 527 For logical expressions @&&@ and @||@, arguments are implicitly cast to @bool@, and follow the rules fr cast expression above. 528 529 For the ternary conditional expression, the condition is implicitly cast to @bool@, and the branch expressions must have compatible types. 530 Each pair of compatible branch expression types produce a possible interpretation, and the cost is defined as the sum of the expression costs plus the sum of conversion costs to the common type. 531 532 \TODO{Write a specification for expression costs.} 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. 533 580 534 581 535 582 \subsection{Assertion Satisfaction} 536 583 537 The resolver tries to satisfy assertions on expressions only when it is needed: either while selecting from multiple alternatives of a same result type for a function call (step \ref{p:returntype} of resolving function calls) or upon reaching the top level of an expression statement. 538 539 Unsatisfiable alternatives are discarded. 540 Satisfiable alternatives receive \textbf{implicit parameters}: in \CFA, parametric functions may be separately compiled, as opposed to \CC templates which are only compiled at instantiation. 541 Given the parametric function-definition: 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: 542 592 \begin{C++} 543 593 forall (otype T | {void foo(T);}) 544 594 void bar (T t) { foo(t); } 545 595 \end{C++} 546 the function @bar@ does not know which @foo@ to call when compiled without knowing the call site, so it requests a function pointer to be passed as an extra argument. 547 At the call site, implicit parameters are automatically inserted by the compiler. 548 549 \TODO{Explain how recursive assertion satisfaction and polymorphic recursion work.} 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. 550 601 551 602 … … 554 605 \subsection{Test Suites} 555 606 556 Automatic test suites are located under the @tests/@ directory. 557 A test case consists of an input CFA source file (suffix @.cfa@), and an expected output file located in the @tests/.expect/@ directory, with the same file name ending with suffix @.txt@. 558 For example, the test named @tests/tuple/tupleCast.cfa@ has the following files, for example: 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: 559 611 \begin{C++} 560 612 tests/ 561 tuple/ 562 .expect/ 563 tupleCast.txt 564 tupleCast.cfa 565 \end{C++} 566 If compilation fails, the error output is compared to the expect file. 567 If the compilation succeeds but does not generate an executable, the compilation output is compared to the expect file. 568 If the compilation succeeds and generates an executable, the executable is run and its output is compared to the expect file. 569 To run the tests, execute the test script @test.py@ under the @tests/@ directory, with a list of test names to be run, or @--all@ (or @make all-tests@) to run all tests. 570 The test script reports test cases fail/success, compilation time and program run time. 571 To see all the options available for @test.py@ using the @--help@ option. 613 .. tuple/ 614 ...... .expect/ 615 .......... tupleCast.txt 616 ...... tupleCast.cfa 617 \end{C++} 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. 572 623 573 624 574 625 \subsection{Performance Reports} 575 626 576 To turn on performance reports, pass the @-XCFA -S@ flag to the compiler. 577 Three kinds of performance reports are available: 627 To turn on performance reports, pass @-S@ flag to the compiler. 628 629 3 kinds of performance reports are available: 578 630 \begin{enumerate} 579 631 \item … … 587 639 @Common/Stats/Counter.h@. 588 640 \end{enumerate} 589 It is suggested to run performance tests with optimiz ation (@g++@ flag @-O3@).641 It is suggested to run performance tests with optimized build (@g++@ flag @-O3@) 590 642 591 643 -
doc/user/user.tex
rc7806122 r91fb850 11 11 %% Created On : Wed Apr 6 14:53:29 2016 12 12 %% Last Modified By : Peter A. Buhr 13 %% Last Modified On : Thu Sep 24 16:34:52 202014 %% Update Count : 39 9713 %% Last Modified On : Fri Mar 6 13:34:52 2020 14 %% Update Count : 3924 15 15 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 16 … … 30 30 \usepackage{upquote} % switch curled `'" to straight 31 31 \usepackage{calc} 32 \usepackage{xspace} 32 33 \usepackage{varioref} % extended references 33 \usepackage[labelformat=simple,aboveskip=0pt,farskip=0pt]{subfig} 34 \renewcommand{\thesubfigure}{\alph{subfigure})} 34 \usepackage{listings} % format program code 35 35 \usepackage[flushmargin]{footmisc} % support label/reference in footnote 36 36 \usepackage{latexsym} % \Box glyph 37 37 \usepackage{mathptmx} % better math font with "times" 38 38 \usepackage[usenames]{color} 39 \newcommand{\CFALatin}{} 39 \input{common} % common CFA document macros 40 \usepackage[dvips,plainpages=false,pdfpagelabels,pdfpagemode=UseNone,colorlinks=true,pagebackref=true,linkcolor=blue,citecolor=blue,urlcolor=blue,pagebackref=true,breaklinks=true]{hyperref} 41 \usepackage{breakurl} 42 43 \usepackage[pagewise]{lineno} 44 \renewcommand{\linenumberfont}{\scriptsize\sffamily} 45 \usepackage[firstpage]{draftwatermark} 46 \SetWatermarkLightness{0.9} 47 48 % Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore 49 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR 50 % AFTER HYPERREF. 51 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}} 52 53 \setlength{\topmargin}{-0.45in} % move running title into header 54 \setlength{\headsep}{0.25in} 55 56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 57 58 \CFAStyle % use default CFA format-style 59 \lstnewenvironment{C++}[1][] % use C++ style 60 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}} 61 {} 62 40 63 % inline code ©...© (copyright symbol) emacs: C-q M-) 41 64 % red highlighting ®...® (registered trademark symbol) emacs: C-q M-. … … 45 68 % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^ 46 69 % math escape $...$ (dollar symbol) 47 \input{common} % common CFA document macros48 \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 underscore59 % removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR60 % AFTER HYPERREF.61 \renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}62 63 \setlength{\topmargin}{-0.45in} % move running title into header64 \setlength{\headsep}{0.25in}65 66 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%67 68 \CFADefaults % use default CFA format-style69 \lstnewenvironment{C++}[1][] % use C++ style70 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}71 {}72 73 \newsavebox{\myboxA}74 \newsavebox{\myboxB}75 70 76 71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 84 79 \newcommand{\G}[1]{{\Textbf[OliveGreen]{#1}}} 85 80 \newcommand{\KWC}{K-W C\xspace} 81 82 \newsavebox{\LstBox} 86 83 87 84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 256 253 257 254 The signature feature of \CFA is \emph{\Index{overload}able} \Index{parametric-polymorphic} functions~\cite{forceone:impl,Cormack90,Duggan96} with functions generalized using a ©forall© clause (giving the language its name): 258 \begin{ cfa}255 \begin{lstlisting} 259 256 ®forall( otype T )® T identity( T val ) { return val; } 260 257 int forty_two = identity( 42 ); §\C{// T is bound to int, forty\_two == 42}§ 261 \end{ cfa}258 \end{lstlisting} 262 259 % extending the C type system with parametric polymorphism and overloading, as opposed to the \Index*[C++]{\CC{}} approach of object-oriented extensions. 263 260 \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}. … … 278 275 \begin{comment} 279 276 A simple example is leveraging the existing type-unsafe (©void *©) C ©bsearch© to binary search a sorted floating array: 280 \begin{ cfa}277 \begin{lstlisting} 281 278 void * bsearch( const void * key, const void * base, size_t dim, size_t size, 282 279 int (* compar)( const void *, const void * )); … … 287 284 double key = 5.0, vals[10] = { /* 10 sorted floating values */ }; 288 285 double * val = (double *)bsearch( &key, vals, 10, sizeof(vals[0]), comp ); §\C{// search sorted array}§ 289 \end{ cfa}286 \end{lstlisting} 290 287 which can be augmented simply with a polymorphic, type-safe, \CFA-overloaded wrappers: 291 \begin{ cfa}288 \begin{lstlisting} 292 289 forall( otype T | { int ?<?( T, T ); } ) T * bsearch( T key, const T * arr, size_t size ) { 293 290 int comp( const void * t1, const void * t2 ) { /* as above with double changed to T */ } … … 300 297 double * val = bsearch( 5.0, vals, 10 ); §\C{// selection based on return type}§ 301 298 int posn = bsearch( 5.0, vals, 10 ); 302 \end{ cfa}299 \end{lstlisting} 303 300 The nested function ©comp© provides the hidden interface from typed \CFA to untyped (©void *©) C, plus the cast of the result. 304 301 Providing a hidden ©comp© function in \CC is awkward as lambdas do not use C calling-conventions and template declarations cannot appear at block scope. … … 308 305 \CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations. 309 306 For example, it is possible to write a type-safe \CFA wrapper ©malloc© based on the C ©malloc©: 310 \begin{ cfa}307 \begin{lstlisting} 311 308 forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); } 312 309 int * ip = malloc(); §\C{// select type and size from left-hand side}§ 313 310 double * dp = malloc(); 314 311 struct S {...} * sp = malloc(); 315 \end{ cfa}312 \end{lstlisting} 316 313 where the return type supplies the type/size of the allocation, which is impossible in most type systems. 317 314 \end{comment} … … 946 943 the same level as a ©case© clause; the target label may be case ©default©, but only associated 947 944 with 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} 948 980 949 981 \begin{figure} … … 1054 1086 1055 1087 1056 \subsection{Loop Control}1057 1058 The ©for©/©while©/©do-while© loop-control allows empty or simplified ranges (see Figure~\ref{f:LoopControlExamples}).1059 \begin{itemize}1060 \item1061 The loop index is polymorphic in the type of the comparison value N (when the start value is implicit) or the start value M.1062 \item1063 An empty conditional implies comparison value of ©1© (true).1064 \item1065 A comparison N is implicit up-to exclusive range [0,N©®)®©.1066 \item1067 A comparison ©=© N is implicit up-to inclusive range [0,N©®]®©.1068 \item1069 The up-to range M ©~©\index{~@©~©} N means exclusive range [M,N©®)®©.1070 \item1071 The up-to range M ©~=©\index{~=@©~=©} N means inclusive range [M,N©®]®©.1072 \item1073 The down-to range M ©-~©\index{-~@©-~©} N means exclusive range [N,M©®)®©.1074 \item1075 The down-to range M ©-~=©\index{-~=@©-~=©} N means inclusive range [N,M©®]®©.1076 \item1077 ©0© is the implicit start value;1078 \item1079 ©1© is the implicit increment value.1080 \item1081 The up-to range uses operator ©+=© for increment;1082 \item1083 The down-to range uses operator ©-=© for decrement.1084 \item1085 ©@© means put nothing in this field.1086 \item1087 ©:© means start another index.1088 \end{itemize}1089 1090 1091 1088 %\subsection{\texorpdfstring{Labelled \protect\lstinline@continue@ / \protect\lstinline@break@}{Labelled continue / break}} 1092 1089 \subsection{\texorpdfstring{Labelled \LstKeywordStyle{continue} / \LstKeywordStyle{break} Statement}{Labelled continue / break Statement}} … … 1098 1095 for ©break©, the target label can also be associated with a ©switch©, ©if© or compound (©{}©) statement. 1099 1096 \VRef[Figure]{f:MultiLevelExit} shows ©continue© and ©break© indicating the specific control structure, and the corresponding C program using only ©goto© and labels. 1100 The innermost loop has 8exit points, which cause continuation or termination of one or more of the 7 \Index{nested control-structure}s.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. 1101 1098 1102 1099 \begin{figure} 1103 \centering 1104 \begin{lrbox}{\myboxA} 1105 \begin{cfa}[tabsize=3] 1106 ®Compound:® { 1107 ®Try:® try { 1108 ®For:® for ( ... ) { 1109 ®While:® while ( ... ) { 1110 ®Do:® do { 1111 ®If:® if ( ... ) { 1112 ®Switch:® switch ( ... ) { 1113 case 3: 1114 ®break Compound®; 1115 ®break Try®; 1116 ®break For®; /* or */ ®continue For®; 1117 ®break While®; /* or */ ®continue While®; 1118 ®break Do®; /* or */ ®continue Do®; 1119 ®break If®; 1120 ®break Switch®; 1121 } // switch 1122 } else { 1123 ... ®break If®; ... // terminate if 1124 } // if 1125 } while ( ... ); // do 1126 } // while 1127 } // for 1128 } ®finally® { // always executed 1129 } // try 1100 \begin{tabular}{@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}} 1101 \multicolumn{1}{@{\hspace{\parindentlnth}}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}} \\ 1102 \begin{cfa} 1103 ®LC:® { 1104 ... §declarations§ ... 1105 ®LS:® switch ( ... ) { 1106 case 3: 1107 ®LIF:® if ( ... ) { 1108 ®LF:® for ( ... ) { 1109 ®LW:® while ( ... ) { 1110 ... break ®LC®; ... 1111 ... break ®LS®; ... 1112 ... break ®LIF®; ... 1113 ... continue ®LF;® ... 1114 ... break ®LF®; ... 1115 ... continue ®LW®; ... 1116 ... break ®LW®; ... 1117 } // while 1118 } // for 1119 } else { 1120 ... break ®LIF®; ... 1121 } // if 1122 } // switch 1130 1123 } // compound 1131 1124 \end{cfa} 1132 \end{lrbox} 1133 1134 \begin{lrbox}{\myboxB} 1135 \begin{cfa}[tabsize=3] 1125 & 1126 \begin{cfa} 1136 1127 { 1137 1138 ®ForC:® for ( ... ) { 1139 ®WhileC:® while ( ... ) { 1140 ®DoC:® do { 1141 if ( ... ) { 1142 switch ( ... ) { 1143 case 3: 1144 ®goto Compound®; 1145 ®goto Try®; 1146 ®goto ForB®; /* or */ ®goto ForC®; 1147 ®goto WhileB®; /* or */ ®goto WhileC®; 1148 ®goto DoB®; /* or */ ®goto DoC®; 1149 ®goto If®; 1150 ®goto Switch®; 1151 } ®Switch:® ; 1152 } else { 1153 ... ®goto If®; ... // terminate if 1154 } ®If:®; 1155 } while ( ... ); ®DoB:® ; 1156 } ®WhileB:® ; 1157 } ®ForB:® ; 1158 1159 1160 } ®Compound:® ; 1161 \end{cfa} 1162 \end{lrbox} 1163 1164 \subfloat[\CFA]{\label{f:CFibonacci}\usebox\myboxA} 1165 \hspace{2pt} 1166 \vrule 1167 \hspace{2pt} 1168 \subfloat[C]{\label{f:CFAFibonacciGen}\usebox\myboxB} 1128 ... §declarations§ ... 1129 switch ( ... ) { 1130 case 3: 1131 if ( ... ) { 1132 for ( ... ) { 1133 while ( ... ) { 1134 ... goto ®LC®; ... 1135 ... goto ®LS®; ... 1136 ... goto ®LIF®; ... 1137 ... goto ®LFC®; ... 1138 ... goto ®LFB®; ... 1139 ... goto ®LWC®; ... 1140 ... goto ®LWB®; ... 1141 ®LWC®: ; } ®LWB:® ; 1142 ®LFC:® ; } ®LFB:® ; 1143 } else { 1144 ... goto ®LIF®; ... 1145 } ®L3:® ; 1146 } ®LS:® ; 1147 } ®LC:® ; 1148 \end{cfa} 1149 & 1150 \begin{cfa} 1151 1152 1153 1154 1155 1156 1157 1158 // terminate compound 1159 // terminate switch 1160 // terminate if 1161 // continue loop 1162 // terminate loop 1163 // continue loop 1164 // terminate loop 1165 1166 1167 1168 // terminate if 1169 1170 1171 1172 \end{cfa} 1173 \end{tabular} 1169 1174 \caption{Multi-level Exit} 1170 1175 \label{f:MultiLevelExit} … … 1421 1426 try { 1422 1427 f(...); 1423 } catch( E e ; §boolean-predicate§ ) { §\C {// termination handler}§1428 } catch( E e ; §boolean-predicate§ ) { §\C[8cm]{// termination handler}§ 1424 1429 // recover and continue 1425 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler} §1430 } catchResume( E e ; §boolean-predicate§ ) { §\C{// resumption handler}\CRT§ 1426 1431 // repair and return 1427 1432 } finally { … … 3486 3491 For 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. 3487 3492 \begin{cquote} 3488 \begin{lrbox}{\ myboxA}3493 \begin{lrbox}{\LstBox} 3489 3494 \begin{cfa}[aboveskip=0pt,belowskip=0pt] 3490 3495 int x; double y char z; … … 3492 3497 \end{lrbox} 3493 3498 \begin{tabular}{@{}l@{\hspace{3em}}l@{\hspace{3em}}l@{}} 3494 \multicolumn{1}{@{}l@{}}{\usebox\ myboxA} \\3499 \multicolumn{1}{@{}l@{}}{\usebox\LstBox} \\ 3495 3500 \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2em}}}{\textbf{\CC}} & \multicolumn{1}{c}{\textbf{Python}} \\ 3496 3501 \begin{cfa}[aboveskip=0pt,belowskip=0pt] … … 6667 6672 For 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. 6668 6673 Without 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}6672 6674 6673 6675 \CFA memory management extends allocation to support constructors for initialization of allocated storage, \eg in … … 6719 6721 6720 6722 // §\CFA§ safe general allocation, fill, resize, alignment, array 6721 T * alloc( void );§\indexc{alloc}§ §\C[3.5in]{// variable, T size}§ 6722 T * alloc( size_t dim ); §\C{// array[dim], T size elements}§ 6723 T * alloc( T ptr[], size_t dim ); §\C{// realloc array[dim], T size elements}§ 6724 6725 T * alloc_set( char fill );§\indexc{alloc_set}§ §\C{// variable, T size, fill bytes with value}§ 6726 T * alloc_set( T fill ); §\C{// variable, T size, fill with value}§ 6727 T * alloc_set( size_t dim, char fill ); §\C{// array[dim], T size elements, fill bytes with value}§ 6728 T * alloc_set( size_t dim, T fill ); §\C{// array[dim], T size elements, fill elements with value}§ 6729 T * alloc_set( size_t dim, const T fill[] ); §\C{// array[dim], T size elements, fill elements with array}§ 6730 T * alloc_set( T ptr[], size_t dim, char fill ); §\C{// realloc array[dim], T size elements, fill bytes with value}§ 6731 6732 T * alloc_align( size_t align ); §\C{// aligned variable, T size}§ 6733 T * alloc_align( size_t align, size_t dim ); §\C{// aligned array[dim], T size elements}§ 6734 T * alloc_align( T ptr[], size_t align ); §\C{// realloc new aligned array}§ 6735 T * alloc_align( T ptr[], size_t align, size_t dim ); §\C{// realloc new aligned array[dim]}§ 6736 6737 T * alloc_align_set( size_t align, char fill ); §\C{// aligned variable, T size, fill bytes with value}§ 6738 T * alloc_align_set( size_t align, T fill ); §\C{// aligned variable, T size, fill with value}§ 6739 T * alloc_align_set( size_t align, size_t dim, char fill ); §\C{// aligned array[dim], T size elements, fill bytes with value}§ 6740 T * alloc_align_set( size_t align, size_t dim, T fill ); §\C{// aligned array[dim], T size elements, fill elements with value}§ 6741 T * alloc_align_set( size_t align, size_t dim, const T fill[] ); §\C{// aligned array[dim], T size elements, fill elements with array}§ 6742 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); §\C{// realloc new aligned array[dim], fill new bytes with value}§ 6723 T * alloc( void );§\indexc{alloc}§ 6724 T * alloc( size_t dim ); 6725 T * alloc( T ptr[], size_t dim ); 6726 T * alloc_set( char fill );§\indexc{alloc_set}§ 6727 T * alloc_set( T fill ); 6728 T * alloc_set( size_t dim, char fill ); 6729 T * alloc_set( size_t dim, T fill ); 6730 T * alloc_set( size_t dim, const T fill[] ); 6731 T * alloc_set( T ptr[], size_t dim, char fill ); 6732 6733 T * alloc_align( size_t align ); 6734 T * alloc_align( size_t align, size_t dim ); 6735 T * alloc_align( T ptr[], size_t align ); // aligned realloc array 6736 T * alloc_align( T ptr[], size_t align, size_t dim ); // aligned realloc array 6737 T * alloc_align_set( size_t align, char fill ); 6738 T * alloc_align_set( size_t align, T fill ); 6739 T * alloc_align_set( size_t align, size_t dim, char fill ); 6740 T * alloc_align_set( size_t align, size_t dim, T fill ); 6741 T * alloc_align_set( size_t align, size_t dim, const T fill[] ); 6742 T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); 6743 6743 6744 6744 // §\CFA§ safe initialization/copy, i.e., implicit size specification -
src/AST/Convert.cpp
rc7806122 r91fb850 177 177 const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final { 178 178 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 decl182 // must be handled **differently** on convert back to old.183 auto ftype = new FunctionType(184 cv(node->type),185 (bool)node->type->isVarArgs186 );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 194 179 auto decl = new FunctionDecl( 195 180 node->name, 196 181 Type::StorageClasses( node->storage.val ), 197 182 LinkageSpec::Spec( node->linkage.val ), 198 ftype, 199 //get<FunctionType>().accept1( node->type ), 183 get<FunctionType>().accept1( node->type ), 200 184 {}, 201 185 get<Attribute>().acceptL( node->attributes ), … … 1168 1152 1169 1153 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 1173 1154 auto ty = new FunctionType { 1174 1155 cv( node ), 1175 1156 (bool)node->isVarArgs 1176 1157 }; 1177 auto returns = get<Type>().acceptL(node->returns); 1178 auto params = get<Type>().acceptL(node->params); 1179 1180 int ret_index = 0; 1181 for (auto t: returns) { 1182 // xxx - LinkageSpec shouldn't matter but needs to be something 1183 ObjectDecl * dummy = new ObjectDecl(dummy_returnvar_prefix + std::to_string(ret_index++), {}, LinkageSpec::C, nullptr, t, nullptr); 1184 ty->returnVals.push_back(dummy); 1185 } 1186 int param_index = 0; 1187 for (auto t: params) { 1188 ObjectDecl * dummy = new ObjectDecl(dummy_paramvar_prefix + std::to_string(param_index++), {}, LinkageSpec::C, nullptr, t, nullptr); 1189 ty->parameters.push_back(dummy); 1190 } 1191 1192 // ty->returnVals = get<DeclarationWithType>().acceptL( node->returns ); 1193 // ty->parameters = get<DeclarationWithType>().acceptL( node->params ); 1158 ty->returnVals = get<DeclarationWithType>().acceptL( node->returns ); 1159 ty->parameters = get<DeclarationWithType>().acceptL( node->params ); 1194 1160 ty->forall = get<TypeDecl>().acceptL( node->forall ); 1195 1161 return visitType( node, ty ); … … 1408 1374 ast::Node * node = nullptr; 1409 1375 /// cache of nodes that might be referenced by readonly<> for de-duplication 1410 /// in case that some nodes are dropped by conversion (due to possible structural change) 1411 /// use smart pointers in cache value to prevent accidental invalidation. 1412 /// at conversion stage, all created nodes are guaranteed to be unique, therefore 1413 /// const_casting out of smart pointers is permitted. 1414 std::unordered_map< const BaseSyntaxNode *, ast::ptr<ast::Node> > cache = {}; 1376 std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {}; 1415 1377 1416 1378 // Local Utilities: … … 1485 1447 auto it = cache.find( old ); 1486 1448 if ( it == cache.end() ) return false; 1487 node = const_cast<ast::Node *>(it->second.get());1449 node = it->second; 1488 1450 return true; 1489 1451 } … … 1524 1486 virtual void visit( const FunctionDecl * old ) override final { 1525 1487 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 them1531 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 1544 1488 auto decl = new ast::FunctionDecl{ 1545 1489 old->location, 1546 1490 old->name, 1547 // GET_ACCEPT_1(type, FunctionType), 1548 std::move(paramVars), 1549 std::move(returnVars), 1491 GET_ACCEPT_1(type, FunctionType), 1550 1492 {}, 1551 1493 { old->storageClasses.val }, … … 1554 1496 { old->get_funcSpec().val } 1555 1497 }; 1556 1557 decl->type = ftype;1558 1498 cache.emplace( old, decl ); 1559 1560 1499 decl->withExprs = GET_ACCEPT_V(withExprs, Expr); 1561 1500 decl->stmts = GET_ACCEPT_1(statements, CompoundStmt); … … 2576 2515 cv( old ) 2577 2516 }; 2578 auto returnVars = GET_ACCEPT_V(returnVals, DeclWithType); 2579 auto paramVars = GET_ACCEPT_V(parameters, DeclWithType); 2580 // ty->returns = GET_ACCEPT_V( returnVals, DeclWithType ); 2581 // ty->params = GET_ACCEPT_V( parameters, DeclWithType ); 2582 for (auto & v: returnVars) { 2583 ty->returns.emplace_back(v->get_type()); 2584 } 2585 for (auto & v: paramVars) { 2586 ty->params.emplace_back(v->get_type()); 2587 } 2517 ty->returns = GET_ACCEPT_V( returnVals, DeclWithType ); 2518 ty->params = GET_ACCEPT_V( parameters, DeclWithType ); 2588 2519 ty->forall = GET_ACCEPT_V( forall, TypeDecl ); 2589 2520 visitType( old, ty ); -
src/AST/Decl.hpp
rc7806122 r91fb850 124 124 class FunctionDecl : public DeclWithType { 125 125 public: 126 std::vector<ptr<DeclWithType>> params;127 std::vector<ptr<DeclWithType>> returns;128 // declared type, derived from parameter declarations129 126 ptr<FunctionType> type; 130 127 ptr<CompoundStmt> stmts; 131 128 std::vector< ptr<Expr> > withExprs; 132 129 133 FunctionDecl( const CodeLocation & loc, const std::string & name, 134 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 130 FunctionDecl( const CodeLocation & loc, const std::string & name, FunctionType * type, 135 131 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, 136 132 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}) 137 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),133 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ), 138 134 stmts( stmts ) {} 139 135 -
src/AST/ForallSubstitutor.hpp
rc7806122 r91fb850 33 33 } 34 34 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 45 35 /// Substitute parameter/return type 46 36 std::vector< ptr< DeclWithType > > operator() ( const std::vector< ptr< DeclWithType > > & o ) { … … 58 48 return n; 59 49 } 60 61 */62 50 }; 63 51 -
src/AST/Pass.impl.hpp
rc7806122 r91fb850 465 465 __pass::symtab::addId( core, 0, func ); 466 466 VISIT( 467 // parameter declarations are now directly here468 maybe_accept( node, &FunctionDecl::params );469 maybe_accept( node, &FunctionDecl::returns );470 // foralls are still in function type471 467 maybe_accept( node, &FunctionDecl::type ); 472 468 // function body needs to have the same scope as parameters - CompoundStmt will not enter -
src/AST/SymbolTable.cpp
rc7806122 r91fb850 335 335 } 336 336 337 /*338 337 void SymbolTable::addFunctionType( const FunctionType * ftype ) { 339 338 addTypes( ftype->forall ); … … 341 340 addIds( ftype->params ); 342 341 } 343 */344 342 345 343 void SymbolTable::lazyInitScope() { … … 370 368 assert( ! params.empty() ); 371 369 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 372 const Type * base = InitTweak::getPointerBase( params.front() );370 const Type * base = InitTweak::getPointerBase( params.front()->get_type() ); 373 371 assert( base ); 374 372 return Mangle::mangle( base ); -
src/AST/SymbolTable.hpp
rc7806122 r91fb850 145 145 146 146 /// 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 ); 148 148 149 149 private: -
src/AST/Type.cpp
rc7806122 r91fb850 102 102 // --- FunctionType 103 103 104 105 104 FunctionType::FunctionType( const FunctionType & o ) 106 105 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(), … … 113 112 114 113 namespace { 115 bool containsTtype( const std::vector<ptr< Type>> & l ) {114 bool containsTtype( const std::vector<ptr<DeclWithType>> & l ) { 116 115 if ( ! l.empty() ) { 117 return Tuples::isTtype( l.back() );116 return Tuples::isTtype( l.back()->get_type() ); 118 117 } 119 118 return false; -
src/AST/Type.hpp
rc7806122 r91fb850 302 302 class FunctionType final : public ParameterizedType { 303 303 public: 304 // std::vector<ptr<DeclWithType>> returns; 305 // std::vector<ptr<DeclWithType>> params; 306 307 std::vector<ptr<Type>> returns; 308 std::vector<ptr<Type>> params; 304 std::vector<ptr<DeclWithType>> returns; 305 std::vector<ptr<DeclWithType>> params; 309 306 310 307 /// Does the function accept a variable number of arguments following the arguments specified -
src/InitTweak/InitTweak.cc
rc7806122 r91fb850 1026 1026 if ( ftype->params.size() != 2 ) return false; 1027 1027 1028 const ast::Type * t1 = getPointerBase( ftype->params.front() );1028 const ast::Type * t1 = getPointerBase( ftype->params.front()->get_type() ); 1029 1029 if ( ! t1 ) return false; 1030 const ast::Type * t2 = ftype->params.back() ;1030 const ast::Type * t2 = ftype->params.back()->get_type(); 1031 1031 1032 1032 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} ); -
src/ResolvExpr/CandidateFinder.cpp
rc7806122 r91fb850 188 188 189 189 // 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(); 191 191 cand->expr = ast::mutate_field_index( 192 192 appExpr, &ast::ApplicationExpr::args, i, 193 193 computeExpressionConversionCost( 194 args[i], *param, symtab, cand->env, convCost ) );195 convCost.decSpec( specCost( *param) );194 args[i], paramType, symtab, cand->env, convCost ) ); 195 convCost.decSpec( specCost( paramType ) ); 196 196 ++param; // can't be in for-loop update because of the continue 197 197 } … … 698 698 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) { 699 699 // attempt to narrow based on expected target type 700 const ast::Type * returnType = funcType->returns.front() ;700 const ast::Type * returnType = funcType->returns.front()->get_type(); 701 701 if ( ! unify( 702 702 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) … … 712 712 std::size_t genStart = 0; 713 713 714 // xxx - how to handle default arg after change to ftype representation? 715 if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) { 716 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) { 717 // function may have default args only if directly calling by name 718 // must use types on candidate however, due to RenameVars substitution 719 auto nParams = funcType->params.size(); 720 721 for (size_t i=0; i<nParams; ++i) { 722 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 723 if (!instantiateArgument( 724 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 725 } 726 goto endMatch; 727 } 728 } 729 for ( const auto & param : funcType->params ) { 714 for ( const ast::DeclWithType * param : funcType->params ) { 715 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param ); 730 716 // Try adding the arguments corresponding to the current parameter to the existing 731 717 // matches 732 // no default args for indirect calls733 718 if ( ! instantiateArgument( 734 param, nullptr, args, results, genStart, symtab ) ) return; 735 } 736 737 endMatch: 719 obj->type, obj->init, args, results, genStart, symtab ) ) return; 720 } 721 738 722 if ( funcType->isVarArgs ) { 739 723 // append any unused arguments to vararg pack -
src/ResolvExpr/CurrentObject.cc
rc7806122 r91fb850 594 594 class SimpleIterator final : public MemberIterator { 595 595 CodeLocation location; 596 const Type *type = nullptr;596 readonly< Type > type = nullptr; 597 597 public: 598 598 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {} … … 630 630 class ArrayIterator final : public MemberIterator { 631 631 CodeLocation location; 632 const ArrayType *array = nullptr;633 const Type *base = nullptr;632 readonly< ArrayType > array = nullptr; 633 readonly< Type > base = nullptr; 634 634 size_t index = 0; 635 635 size_t size = 0; -
src/ResolvExpr/Resolver.cc
rc7806122 r91fb850 1223 1223 template<typename Iter> 1224 1224 inline bool nextMutex( Iter & it, const Iter & end ) { 1225 while ( it != end && ! (*it)-> is_mutex() ) { ++it; }1225 while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; } 1226 1226 return it != end; 1227 1227 } … … 1638 1638 // Check if the argument matches the parameter type in the current 1639 1639 // scope 1640 //ast::ptr< ast::Type > paramType = (*param)->get_type();1640 ast::ptr< ast::Type > paramType = (*param)->get_type(); 1641 1641 if ( 1642 1642 ! unify( 1643 arg->expr->result, *param, resultEnv, need, have, open,1643 arg->expr->result, paramType, resultEnv, need, have, open, 1644 1644 symtab ) 1645 1645 ) { … … 1648 1648 ss << "candidate function not viable: no known conversion " 1649 1649 "from '"; 1650 ast::print( ss, *param);1650 ast::print( ss, (*param)->get_type() ); 1651 1651 ss << "' to '"; 1652 1652 ast::print( ss, arg->expr->result ); -
src/ResolvExpr/SatisfyAssertions.cpp
rc7806122 r91fb850 318 318 if ( ! func ) continue; 319 319 320 for ( const a uto ¶m : func->params ) {321 cost.decSpec( specCost( param ) );320 for ( const ast::DeclWithType * param : func->params ) { 321 cost.decSpec( specCost( param->get_type() ) ); 322 322 } 323 323 -
src/ResolvExpr/SpecCost.cc
rc7806122 r91fb850 178 178 void previsit( const ast::FunctionType * fty ) { 179 179 int minCount = std::numeric_limits<int>::max(); 180 updateMinimumPresent( minCount, fty->params, type_deref);181 updateMinimumPresent( minCount, fty->returns, type_deref);180 updateMinimumPresent( minCount, fty->params, decl_type ); 181 updateMinimumPresent( minCount, fty->returns, decl_type ); 182 182 // Add another level to minCount if set. 183 183 count = toNoneOrInc( minCount ); -
src/ResolvExpr/Unify.cc
rc7806122 r91fb850 395 395 396 396 template< typename Iterator1, typename Iterator2 > 397 bool unify TypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {397 bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 398 398 auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); }; 399 399 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { … … 489 489 || flatOther->isTtype() 490 490 ) { 491 if ( unify TypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {492 if ( unify TypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {491 if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 492 if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 493 493 494 494 // the original types must be used in mark assertions, since pointer comparisons are used … … 784 784 785 785 /// returns flattened version of `src` 786 static std::vector< ast::ptr< ast:: Type > > flattenList(787 const std::vector< ast::ptr< ast:: Type > > & src, ast::TypeEnvironment & env786 static std::vector< ast::ptr< ast::DeclWithType > > flattenList( 787 const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env 788 788 ) { 789 std::vector< ast::ptr< ast:: Type > > dst;789 std::vector< ast::ptr< ast::DeclWithType > > dst; 790 790 dst.reserve( src.size() ); 791 for ( const a uto &d : src ) {791 for ( const ast::DeclWithType * d : src ) { 792 792 ast::Pass<TtypeExpander_new> expander{ env }; 793 793 // TtypeExpander pass is impure (may mutate nodes in place) 794 794 // need to make nodes shared to prevent accidental mutation 795 ast::ptr<ast:: Type> dc = d->accept(expander);796 auto types = flatten( dc );795 ast::ptr<ast::DeclWithType> dc = d->accept(expander); 796 auto types = flatten( dc->get_type() ); 797 797 for ( ast::ptr< ast::Type > & t : types ) { 798 798 // outermost const, volatile, _Atomic qualifiers in parameters should not play … … 803 803 // requirements than a non-mutex function 804 804 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 805 dst.emplace_back( t);805 dst.emplace_back( new ast::ObjectDecl{ dc->location, "", t } ); 806 806 } 807 807 } … … 811 811 /// Creates a tuple type based on a list of DeclWithType 812 812 template< typename Iter > 813 static ast::ptr< ast::Type > tupleFrom Types( Iter crnt, Iter end ) {813 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) { 814 814 std::vector< ast::ptr< ast::Type > > types; 815 815 while ( crnt != end ) { 816 816 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 817 817 // that this results in a flat tuple 818 flatten( *crnt, types );818 flatten( (*crnt)->get_type(), types ); 819 819 820 820 ++crnt; … … 825 825 826 826 template< typename Iter > 827 static bool unify TypeList(827 static bool unifyDeclList( 828 828 Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env, 829 829 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, … … 831 831 ) { 832 832 while ( crnt1 != end1 && crnt2 != end2 ) { 833 const ast::Type * t1 = *crnt1;834 const ast::Type * t2 = *crnt2;833 const ast::Type * t1 = (*crnt1)->get_type(); 834 const ast::Type * t2 = (*crnt2)->get_type(); 835 835 bool isTuple1 = Tuples::isTtype( t1 ); 836 836 bool isTuple2 = Tuples::isTtype( t2 ); … … 840 840 // combine remainder of list2, then unify 841 841 return unifyExact( 842 t1, tupleFrom Types( crnt2, end2 ), env, need, have, open,842 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 843 843 noWiden(), symtab ); 844 844 } else if ( ! isTuple1 && isTuple2 ) { 845 845 // combine remainder of list1, then unify 846 846 return unifyExact( 847 tupleFrom Types( crnt1, end1 ), t2, env, need, have, open,847 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 848 848 noWiden(), symtab ); 849 849 } … … 860 860 if ( crnt1 != end1 ) { 861 861 // try unifying empty tuple with ttype 862 const ast::Type * t1 = *crnt1;862 const ast::Type * t1 = (*crnt1)->get_type(); 863 863 if ( ! Tuples::isTtype( t1 ) ) return false; 864 864 return unifyExact( 865 t1, tupleFrom Types( crnt2, end2 ), env, need, have, open,865 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 866 866 noWiden(), symtab ); 867 867 } else if ( crnt2 != end2 ) { 868 868 // try unifying empty tuple with ttype 869 const ast::Type * t2 = *crnt2;869 const ast::Type * t2 = (*crnt2)->get_type(); 870 870 if ( ! Tuples::isTtype( t2 ) ) return false; 871 871 return unifyExact( 872 tupleFrom Types( crnt1, end1 ), t2, env, need, have, open,872 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 873 873 noWiden(), symtab ); 874 874 } … … 877 877 } 878 878 879 static bool unify TypeList(880 const std::vector< ast::ptr< ast:: Type > > & list1,881 const std::vector< ast::ptr< ast:: Type > > & list2,879 static bool unifyDeclList( 880 const std::vector< ast::ptr< ast::DeclWithType > > & list1, 881 const std::vector< ast::ptr< ast::DeclWithType > > & list2, 882 882 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 883 883 const ast::OpenVarSet & open, const ast::SymbolTable & symtab 884 884 ) { 885 return unify TypeList(885 return unifyDeclList( 886 886 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open, 887 887 symtab ); … … 928 928 ) return; 929 929 930 if ( ! unify TypeList( params, params2, tenv, need, have, open, symtab ) ) return;931 if ( ! unify TypeList(930 if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return; 931 if ( ! unifyDeclList( 932 932 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return; 933 933 … … 1232 1232 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) { 1233 1233 if ( func->returns.empty() ) return new ast::VoidType{}; 1234 if ( func->returns.size() == 1 ) return func->returns[0] ;1234 if ( func->returns.size() == 1 ) return func->returns[0]->get_type(); 1235 1235 1236 1236 std::vector<ast::ptr<ast::Type>> tys; 1237 for ( const a uto &decl : func->returns ) {1238 tys.emplace_back( decl );1237 for ( const ast::DeclWithType * decl : func->returns ) { 1238 tys.emplace_back( decl->get_type() ); 1239 1239 } 1240 1240 return new ast::TupleType{ std::move(tys) }; -
src/SymTab/Mangler.cc
rc7806122 r91fb850 551 551 GuardValue( inFunctionType ); 552 552 inFunctionType = true; 553 if (functionType->returns.empty()) mangleName << Encoding::void_t; 554 else accept_each( functionType->returns, *visitor ); 553 std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns ); 554 if (returnTypes.empty()) mangleName << Encoding::void_t; 555 else accept_each( returnTypes, *visitor ); 555 556 mangleName << "_"; 556 accept_each( functionType->params, *visitor ); 557 std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params ); 558 accept_each( paramTypes, *visitor ); 557 559 mangleName << "_"; 558 560 } -
src/SymTab/Validate.cc
rc7806122 r91fb850 1384 1384 /// Replaces enum types by int, and function/array types in function parameter and return 1385 1385 /// lists by appropriate pointers 1386 /*1387 1386 struct EnumAndPointerDecay_new { 1388 1387 const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) { … … 1435 1434 } 1436 1435 }; 1437 */1438 1436 1439 1437 /// expand assertions from a trait instance, performing appropriate type variable substitutions … … 1839 1837 const ast::Type * validateType( 1840 1838 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) { 1841 //ast::Pass< EnumAndPointerDecay_new > epc;1839 ast::Pass< EnumAndPointerDecay_new > epc; 1842 1840 ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab }; 1843 1841 ast::Pass< ForallPointerDecay_new > fpd{ loc }; 1844 1842 1845 return type->accept( lrt )->accept( fpd );1843 return type->accept( epc )->accept( lrt )->accept( fpd ); 1846 1844 } 1847 1845
Note:
See TracChangeset
for help on using the changeset viewer.