Changes in / [22854f8:cb91437]
- Files:
-
- 40 deleted
- 5 edited
-
doc/generic_types/generic_types.tex (modified) (4 diffs)
-
doc/rob_thesis/cfa-format.tex (deleted)
-
doc/rob_thesis/conclusions.tex (deleted)
-
doc/rob_thesis/ctordtor.tex (deleted)
-
doc/rob_thesis/examples/ctor/array_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/copy_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/cv_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/enum_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/expr_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/global_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/hide_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/placement_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/return_dtor.c (deleted)
-
doc/rob_thesis/examples/ctor/static_ctor.c (deleted)
-
doc/rob_thesis/examples/ctor/union_ctor.c (deleted)
-
doc/rob_thesis/examples/intro/FileOutputStream.java (deleted)
-
doc/rob_thesis/examples/intro/compound_lit.c (deleted)
-
doc/rob_thesis/examples/intro/designation.c (deleted)
-
doc/rob_thesis/examples/intro/ignore.c (deleted)
-
doc/rob_thesis/examples/intro/ires.java (deleted)
-
doc/rob_thesis/examples/intro/res.java (deleted)
-
doc/rob_thesis/examples/intro/res1.java (deleted)
-
doc/rob_thesis/examples/intro/res2.java (deleted)
-
doc/rob_thesis/examples/intro/res3.java (deleted)
-
doc/rob_thesis/examples/intro/tuple.cc (deleted)
-
doc/rob_thesis/examples/intro/variadic.java (deleted)
-
doc/rob_thesis/examples/scope_guard.h (deleted)
-
doc/rob_thesis/examples/test_scoped_guard.c (deleted)
-
doc/rob_thesis/examples/tuples/assign.c (deleted)
-
doc/rob_thesis/examples/tuples/cast.c (deleted)
-
doc/rob_thesis/examples/tuples/ctor.c (deleted)
-
doc/rob_thesis/examples/tuples/mrv.c (deleted)
-
doc/rob_thesis/examples/tuples/mrv_1.c (deleted)
-
doc/rob_thesis/examples/tuples/mrv_2.c (deleted)
-
doc/rob_thesis/examples/tuples/mrv_3.c (deleted)
-
doc/rob_thesis/examples/variadic/new.c (deleted)
-
doc/rob_thesis/examples/variadic/print.c (deleted)
-
doc/rob_thesis/intro.tex (deleted)
-
doc/rob_thesis/thesis-frontpgs.tex (deleted)
-
doc/rob_thesis/thesis.tex (deleted)
-
doc/rob_thesis/tuples.tex (deleted)
-
src/GenPoly/Box.cc (modified) (1 diff)
-
src/GenPoly/Specialize.cc (modified) (2 diffs)
-
src/InitTweak/FixInit.cc (modified) (13 diffs)
-
src/libcfa/iostream.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/generic_types/generic_types.tex
r22854f8 rcb91437 1 % take of review (for line numbers) and anonymous (for anonymization) on submission2 1 \documentclass[format=acmlarge, anonymous, review]{acmart} 3 2 4 \ usepackage{listings} % For code listings3 \citestyle{acmauthoryear} 5 4 6 % Useful macros 7 \newcommand{\CFA}{C$\mathbf\forall$} % Cforall symbolic name 8 \newcommand{\CC}{\rm C\kern-.1em\hbox{+\kern-.25em+}} % C++ symbolic name 9 \newcommand{\CCeleven}{\rm C\kern-.1em\hbox{+\kern-.25em+}11} % C++11 symbolic name 10 \newcommand{\CCfourteen}{\rm C\kern-.1em\hbox{+\kern-.25em+}14} % C++14 symbolic name 11 \newcommand{\CCseventeen}{\rm C\kern-.1em\hbox{+\kern-.25em+}17} % C++17 symbolic name 12 5 \newcommand{\CFA}{C$\mathbf\forall$} 13 6 \newcommand{\TODO}{\textbf{TODO}} 14 \newcommand{\eg}{\textit{e}.\textit{g}.}15 \newcommand{\ie}{\textit{i}.\textit{e}.}16 \newcommand{\etc}{\textit{etc}.}17 18 % CFA programming language, based on ANSI C (with some gcc additions)19 \lstdefinelanguage{CFA}[ANSI]{C}{20 morekeywords={_Alignas,_Alignof,__alignof,__alignof__,asm,__asm,__asm__,_At,_Atomic,__attribute,__attribute__,auto,21 _Bool,catch,catchResume,choose,_Complex,__complex,__complex__,__const,__const__,disable,dtype,enable,__extension__,22 fallthrough,fallthru,finally,forall,ftype,_Generic,_Imaginary,inline,__label__,lvalue,_Noreturn,one_t,otype,restrict,_Static_assert,23 _Thread_local,throw,throwResume,trait,try,typeof,__typeof,__typeof__,zero_t},24 }%25 26 \lstset{27 language=CFA,28 columns=fullflexible,29 basicstyle=\linespread{0.9}\sf, % reduce line spacing and use sanserif font30 stringstyle=\tt, % use typewriter font31 tabsize=4, % 4 space tabbing32 xleftmargin=\parindent, % indent code to paragraph indentation33 % extendedchars=true, % allow ASCII characters in the range 128-25534 % escapechar=§, % LaTeX escape in CFA code §...§ (section symbol), emacs: C-q M-'35 mathescape=true, % LaTeX math escape in CFA code $...$36 keepspaces=true, %37 showstringspaces=false, % do not show spaces with cup38 showlines=true, % show blank lines at end of code39 aboveskip=4pt, % spacing above/below code block40 belowskip=3pt,41 % replace/adjust listing characters that look bad in sanserif42 literate={-}{\raisebox{-0.15ex}{\texttt{-}}}1 {^}{\raisebox{0.6ex}{$\scriptscriptstyle\land\,$}}143 {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 {_}{\makebox[1.2ex][c]{\rule{1ex}{0.1ex}}}1 {`}{\ttfamily\upshape\hspace*{-0.1ex}`}144 {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{$\rightarrow$}2,45 % moredelim=**[is][\color{red}]{®}{®}, % red highlighting ®...® (registered trademark symbol) emacs: C-q M-.46 % moredelim=**[is][\color{blue}]{ß}{ß}, % blue highlighting ß...ß (sharp s symbol) emacs: C-q M-_47 % moredelim=**[is][\color{OliveGreen}]{¢}{¢}, % green highlighting ¢...¢ (cent symbol) emacs: C-q M-"48 % moredelim=[is][\lstset{keywords={}}]{¶}{¶}, % keyword escape ¶...¶ (pilcrow symbol) emacs: C-q M-^49 }% lstset50 51 % inline code @...@52 \lstMakeShortInline@53 54 % ACM Information55 \citestyle{acmauthoryear}56 7 57 8 \acmJournal{PACMPL} … … 70 21 } 71 22 \email{a3moss@uwaterloo.ca} 72 73 \author{Robert Schluntz}74 \affiliation{%75 \institution{University of Waterloo}76 \department{David R. Cheriton School of Computer Science}77 \streetaddress{Davis Centre, University of Waterloo}78 \city{Waterloo}79 \state{ON}80 \postcode{N2L 3G1}81 \country{Canada}82 }83 \email{rschlunt@uwaterloo.ca}84 85 \author{Peter Buhr}86 \affiliation{%87 \institution{University of Waterloo}88 \department{David R. Cheriton School of Computer Science}89 \streetaddress{Davis Centre, University of Waterloo}90 \city{Waterloo}91 \state{ON}92 \postcode{N2L 3G1}93 \country{Canada}94 }95 \email{pabuhr@uwaterloo.ca}96 23 97 24 \terms{generic, types} … … 122 49 \ccsdesc[300]{Software and its engineering~Source code generation} 123 50 51 % \abstract{Abstract goes here.} 124 52 \begin{abstract} 125 53 \TODO{} Write abstract. … … 131 59 132 60 \section{Introduction \& Background} 61 \CFA{}\footnote{Pronounced ``C-for-all'', and written \CFA{} or Cforall.} is an evolutionary modernization of the C programming language which aims to add modern language features to C while maintaining both source compatibility with C and a familiar mental model for programmers. This paper describes how generic types are designed and implemented in \CFA{}, and how they interact with \CFA{}'s polymorphic functions. 133 62 134 \CFA{}\footnote{Pronounced ``C-for-all'', and written \CFA{} or Cforall.} is an evolutionary extension of the C programming language which aims to add modern language features to C while maintaining both source compatibility with C and a familiar mental model for programmers. This paper describes how generic types are designed and implemented in \CFA{}, and how they interact with \CFA{}'s polymorphic functions. 135 136 \subsection{Polymorphic Functions} 137 138 \CFA{}'s polymorphism was originally formalized by \citet{Ditchfield92}, and first implemented by \citet{Bilson03}. The signature feature of \CFA{} is parametric-polymorphic functions; such functions are written using a @forall@ clause (which gives the language its name): 139 \begin{lstlisting} 140 forall(otype T) 141 T identity(T x) {is_ 142 return x; 143 } 144 145 int forty_two = identity(42); // T is bound to int, forty_two == 42 146 \end{lstlisting} 147 The @identity@ function above can be applied to any complete object type (or ``@otype@''). The type variable @T@ is transformed into a set of additional implicit parameters to @identity@, which encode sufficient information about @T@ to create and return a variable of that type. The \CFA{} implementation passes the size and alignment of the type represented by an @otype@ parameter, as well as an assignment operator, constructor, copy constructor and destructor. If this extra information is not needed, the type parameter can be declared as @dtype T@, where @dtype@ is short for ``data type''. 148 149 Here, the runtime cost of polymorphism is spread over each polymorphic call, due to passing more arguments to polymorphic functions; preliminary experiments have shown this overhead to be similar to \CC{} virtual function calls. An advantage of this design is that, unlike \CC{} template functions, \CFA{} @forall@ functions are compatible with separate compilation. 150 151 Since bare polymorphic types do not provide a great range of available operations, \CFA{} provides a \emph{type assertion} mechanism to provide further information about a type: 152 \begin{lstlisting} 153 forall(otype T | { T twice(T); }) 154 T four_times(T x) { 155 return twice( twice(x) ); 156 } 157 158 double twice(double d) { return d * 2.0; } // (1) 159 160 double magic = four_times(10.5); // T is bound to double, uses (1) to satisfy type assertion 161 \end{lstlisting} 162 These type assertions may be either variable or function declarations that depend on a polymorphic type variable. @four_times@ can only be called with an argument for which there exists a function named @twice@ that can take that argument and return another value of the same type; a pointer to the appropriate @twice@ function is passed as an additional implicit parameter to the call of @four_times@. 163 164 Monomorphic specializations of polymorphic functions can themselves be used to satisfy type assertions. For instance, @twice@ could have been defined using the \CFA{} syntax for operator overloading as: 165 \begin{lstlisting} 166 forall(otype S | { S ?+?(S, S); }) 167 S twice(S x) { return x + x; } // (2) 168 \end{lstlisting} 169 This version of @twice@ works for any type @S@ that has an addition operator defined for it, and it could have been used to satisfy the type assertion on @four_times@. 170 The compiler accomplishes this by creating a wrapper function calling @twice // (2)@ with @S@ bound to @double@, then providing this wrapper function to @four_times@\footnote{\lstinline@twice // (2)@ could also have had a type parameter named \lstinline@T@; \CFA{} specifies renaming of the type parameters, which would avoid the name conflict with the type variable \lstinline@T@ of \lstinline@four_times@.}. 171 172 \subsection{Traits} 173 174 \CFA{} provides \emph{traits} as a means to name a group of type assertions, as in the example below: 175 \begin{lstlisting} 176 trait has_magnitude(otype T) { 177 bool ?<?(T, T); // comparison operator for T 178 T -?(T); // negation operator for T 179 void ?{}(T*, zero_t); // constructor from 0 literal 180 }; 181 182 forall(otype M | has_magnitude(M)) 183 M abs( M m ) { 184 M zero = { 0 }; // uses zero_t constructor from trait 185 return m < zero ? -m : m; 186 } 187 188 forall(otype M | has_magnitude(M)) 189 M max_magnitude( M a, M b ) { 190 return abs(a) < abs(b) ? b : a; 191 } 192 \end{lstlisting} 193 194 @otype@ is essentially syntactic sugar for the following trait: 195 \begin{lstlisting} 196 trait otype(dtype T | sized(T)) { 197 // sized is a compiler-provided pseudo-trait for types with known size & alignment 198 void ?{}(T*); // default constructor 199 void ?{}(T*, T); // copy constructor 200 T ?=?(T*, T); // assignment operator 201 void ^?{}(T*); // destructor 202 }; 203 \end{lstlisting} 204 205 Semantically, traits are simply a named lists of type assertions, but they may be used for many of the same purposes that interfaces in Java or abstract base classes in \CC{} are used for. Unlike Java interfaces or \CC{} base classes, \CFA{} types do not explicitly state any inheritance relationship to traits they satisfy; this can be considered a form of structural inheritance, similar to implementation of an interface in Go, as opposed to the nominal inheritance model of Java and \CC{}. Nominal inheritance can be simulated with traits using marker variables or functions: 206 \begin{lstlisting} 207 trait nominal(otype T) { 208 T is_nominal; 209 }; 210 211 int is_nominal; // int now satisfies the nominal trait 212 { 213 char is_nominal; // char satisfies the nominal trait 214 } 215 // char no longer satisfies the nominal trait here 216 \end{lstlisting} 217 218 Traits, however, are significantly more powerful than nominal-inheritance interfaces; firstly, due to the scoping rules of the declarations that satisfy a trait's type assertions, a type may not satisfy a trait everywhere that the type is declared, as with @char@ and the @nominal@ trait above. Secondly, traits may be used to declare a relationship among multiple types, a property that may be difficult or impossible to represent in nominal-inheritance type systems: 219 \begin{lstlisting} 220 trait pointer_like(otype Ptr, otype El) { 221 lvalue El *?(Ptr); // Ptr can be dereferenced into a modifiable value of type El 222 } 223 224 struct list { 225 int value; 226 list *next; // may omit "struct" on type names 227 }; 228 229 typedef list *list_iterator; 230 231 lvalue int *?( list_iterator it ) { 232 return it->value; 233 } 234 \end{lstlisting} 235 236 In the example above, @(list_iterator, int)@ satisfies @pointer_like@ by the user-defined dereference function, and @(list_iterator, list)@ also satisfies @pointer_like@ by the built-in dereference operator for pointers. Given a declaration @list_iterator it@, @*it@ can be either an @int@ or a @list@, with the meaning disambiguated by context (\eg, @int x = *it;@ interprets @*it@ as an @int@, while @(*it).value = 42;@ interprets @*it@ as a @list@). 237 While a nominal-inheritance system with associated types could model one of those two relationships by making @El@ an associated type of @Ptr@ in the @pointer_like@ implementation, few such systems could model both relationships simultaneously. 238 239 \section{Generic Types} 240 241 The generic types design for \CFA{} must integrate efficiently and naturally with the existing polymorphic functions in \CFA{}, while retaining backwards compatibility with C; maintaining separate compilation is a particularly important constraint on the design. However, where the concrete parameters of the generic type are known, there should not be extra overhead for the use of a generic type. 242 243 A generic type can be declared by placing a @forall@ specifier on a @struct@ or @union@ declaration, and instantiated using a parenthesized list of types after the type name: 244 \begin{lstlisting} 245 forall(otype R, otype S) struct pair { 246 R first; 247 S second; 248 }; 249 250 forall(otype T) 251 T value( pair(const char*, T) *p ) { return p->second; } 252 253 forall(dtype F, otype T) 254 T value_p( pair(F*, T*) p ) { return *p.second; } 255 256 pair(const char*, int) p = { "magic", 42 }; 257 int magic = value( &p ); 258 259 pair(void*, int*) q = { 0, &p.second }; 260 magic = value_p( q ); 261 double d = 1.0; 262 pair(double*, double*) r = { &d, &d }; 263 d = value_p( r ); 264 \end{lstlisting} 265 266 \CFA{} classifies generic types as either \emph{concrete} or \emph{dynamic}. Dynamic generic types vary in their in-memory layout depending on their type parameters, while concrete generic types have a fixed memory layout regardless of type parameters. A type may have polymorphic parameters but still be concrete; \CFA{} refers to such types as \emph{dtype-static}. Polymorphic pointers are an example of dtype-static types -- @forall(dtype T) T*@ is a polymorphic type, but for any @T@ chosen, @T*@ will have exactly the same in-memory representation as a @void*@, and can therefore be represented by a @void*@ in code generation. 267 268 The \CFA{} compiler instantiates concrete generic types by template-expanding them to fresh struct types; concrete generic types can therefore be used with zero runtime overhead. To enable interoperation between equivalent instantiations of a generic type, the compiler saves the set of instantiations currently in scope and re-uses the generated struct declarations where appropriate. As an example, the concrete instantiation for @pair(const char*, int)@ would look something like this: 269 \begin{lstlisting} 270 struct _pair_conc1 { 271 const char* first; 272 int second; 273 }; 274 \end{lstlisting} 275 276 A concrete generic type with dtype-static parameters is also expanded to a struct type, but this struct type is used for all matching instantiations. In the example above, the @pair(F*, T*)@ parameter to @value_p@ is such a type; its expansion would look something like this, and be used as the type of the variables @q@ and @r@ as well, with casts for member access where appropriate: 277 \begin{lstlisting} 278 struct _pair_conc0 { 279 void* first; 280 void* second; 281 }; 282 \end{lstlisting} 283 284 \TODO{} Maybe move this after the rest of the discussion. 285 This re-use of dtype-static struct instantiations enables some useful programming patterns at zero runtime cost. The most important such pattern is using @forall(dtype T) T*@ as a type-checked replacement for @void*@, as in this example, which takes a @qsort@ or @bsearch@-compatible comparison routine and creates a similar lexicographic comparison for pairs of pointers: 286 \begin{lstlisting} 287 forall(dtype T) 288 int lexcmp( pair(T*, T*)* a, pair(T*, T*)* b, int (*cmp)(T*, T*) ) { 289 int c = cmp(a->first, b->first); 290 if ( c == 0 ) c = cmp(a->second, b->second); 291 return c; 292 } 293 \end{lstlisting} 294 Since @pair(T*, T*)@ is a concrete type, there are no added implicit parameters to @lexcmp@, so the code generated by \CFA{} will be effectively identical to a version of this written in standard C using @void*@, yet the \CFA{} version will be type-checked to ensure that the fields of both pairs and the arguments to the comparison function match in type. 295 296 \TODO{} The second is zero-cost ``tag'' structs. 297 298 \section{Tuples} 299 300 \TODO{} Integrate Rob's work 301 302 \TODO{} Check if we actually can use ttype parameters on generic types (if they set the complete flag, it should work, or nearly so). 303 304 \section{Related Work} 305 306 \TODO{} Talk about \CC{}, Cyclone, \etc{} 307 308 \section{Conclusion} 309 310 \TODO{} 63 \CFA{}'s polymorphism was originally formalized by \citet{Ditchfield92}, and first implemented by \citet{Bilson03}. 311 64 312 65 \bibliographystyle{ACM-Reference-Format} -
src/GenPoly/Box.cc
r22854f8 rcb91437 1298 1298 FunctionType * ftype = functionDecl->get_functionType(); 1299 1299 if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) { 1300 if ( functionDecl->get_name() != "?=?" && ! isPrefix( functionDecl->get_name(), "_thunk" ) && ! isPrefix( functionDecl->get_name(), "_adapter" )) { // xxx - remove check for ?=? once reference types are in; remove check for prefix once thunks properly use ctor/dtors1300 if ( functionDecl->get_name() != "?=?" && ! isPrefix( functionDecl->get_name(), "_thunk" ) ) { // xxx - remove check for ?=? once reference types are in; remove check for prefix once thunks properly use ctor/dtors 1301 1301 assert( ftype->get_returnVals().size() == 1 ); 1302 1302 DeclarationWithType * retval = ftype->get_returnVals().front(); -
src/GenPoly/Specialize.cc
r22854f8 rcb91437 168 168 } 169 169 170 struct EnvTrimmer : public Visitor {171 TypeSubstitution * env, * newEnv;172 EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}173 virtual void visit( TypeDecl * tyDecl ) {174 // transfer known bindings for seen type variables175 if ( Type * t = env->lookup( tyDecl->get_name() ) ) {176 newEnv->add( tyDecl->get_name(), t );177 }178 }179 };180 181 /// reduce environment to just the parts that are referenced in a given expression182 TypeSubstitution * trimEnv( ApplicationExpr * expr, TypeSubstitution * env ) {183 if ( env ) {184 TypeSubstitution * newEnv = new TypeSubstitution();185 EnvTrimmer trimmer( env, newEnv );186 expr->accept( trimmer );187 return newEnv;188 }189 return nullptr;190 }191 192 170 /// Generates a thunk that calls `actual` with type `funType` and returns its address 193 171 Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) { … … 233 211 } 234 212 235 appExpr->set_env( trimEnv( appExpr,env ) );213 appExpr->set_env( maybeClone( env ) ); 236 214 if ( inferParams ) { 237 215 appExpr->get_inferParams() = *inferParams; -
src/InitTweak/FixInit.cc
r22854f8 rcb91437 52 52 namespace { 53 53 typedef std::unordered_map< Expression *, TypeSubstitution * > EnvMap; 54 typedef std::unordered_map< int, int > UnqCount;55 54 56 55 class InsertImplicitCalls final : public GenPoly::PolyMutator { … … 75 74 /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both 76 75 /// arguments and return value temporaries 77 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap , UnqCount & unqCount);76 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap ); 78 77 79 78 typedef SymTab::Indexer Parent; 80 79 using Parent::visit; 81 80 82 ResolveCopyCtors( const EnvMap & envMap , UnqCount & unqCount ) : envMap( envMap ), unqCount( unqCount) {}81 ResolveCopyCtors( const EnvMap & envMap ) : envMap( envMap ) {} 83 82 84 83 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override; … … 95 94 TypeSubstitution * env; 96 95 const EnvMap & envMap; 97 UnqCount & unqCount; // count the number of times each unique expr ID appears98 96 }; 99 97 … … 204 202 class FixCopyCtors final : public GenPoly::PolyMutator { 205 203 public: 206 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}207 204 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression, 208 205 /// and destructors 209 static void fixCopyCtors( std::list< Declaration * > &translationUnit , UnqCount & unqCount);206 static void fixCopyCtors( std::list< Declaration * > &translationUnit ); 210 207 211 208 typedef GenPoly::PolyMutator Parent; … … 214 211 virtual Expression * mutate( UniqueExpr * unqExpr ) override; 215 212 virtual Expression * mutate( StmtExpr * stmtExpr ) override; 216 217 UnqCount & unqCount;218 213 }; 219 214 … … 277 272 278 273 EnvMap envMap; 279 UnqCount unqCount;280 274 281 275 InsertImplicitCalls::insert( translationUnit, envMap ); 282 ResolveCopyCtors::resolveImplicitCalls( translationUnit, envMap , unqCount);276 ResolveCopyCtors::resolveImplicitCalls( translationUnit, envMap ); 283 277 InsertDtors::insert( translationUnit ); 284 278 FixInit::fixInitializers( translationUnit ); 285 279 286 280 // FixCopyCtors must happen after FixInit, so that destructors are placed correctly 287 FixCopyCtors::fixCopyCtors( translationUnit , unqCount);281 FixCopyCtors::fixCopyCtors( translationUnit ); 288 282 289 283 GenStructMemberCalls::generate( translationUnit ); … … 304 298 } 305 299 306 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap , UnqCount & unqCount) {307 ResolveCopyCtors resolver( envMap , unqCount);300 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap ) { 301 ResolveCopyCtors resolver( envMap ); 308 302 acceptAll( translationUnit, resolver ); 309 303 } … … 335 329 } 336 330 337 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit , UnqCount & unqCount) {338 FixCopyCtors fixer ( unqCount );331 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit ) { 332 FixCopyCtors fixer; 339 333 mutateAll( translationUnit, fixer ); 340 334 } … … 526 520 void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) { 527 521 static std::unordered_set< int > vars; 528 unqCount[ unqExpr->get_id() ]++; // count the number of unique expressions for each ID529 522 if ( vars.count( unqExpr->get_id() ) ) { 530 523 // xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated … … 643 636 644 637 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) { 645 unqCount[ unqExpr->get_id() ]--;646 static std::unordered_map< int, std::list< Statement * > > dtors;647 638 static std::unordered_map< int, UniqueExpr * > unqMap; 648 639 static std::unordered_set< int > addDeref; … … 654 645 delete unqExpr->get_result(); 655 646 unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) ); 656 if ( unqCount[ unqExpr->get_id() ] == 0 ) { // insert destructor after the last use of the unique expression657 stmtsToAdd.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );658 }659 647 if ( addDeref.count( unqExpr->get_id() ) ) { 660 648 // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too … … 663 651 return unqExpr; 664 652 } 665 FixCopyCtors fixer( unqCount ); 666 unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup 667 stmtsToAdd.splice( stmtsToAdd.end(), fixer.stmtsToAdd ); 653 unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup 668 654 unqMap[unqExpr->get_id()] = unqExpr; 669 655 if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) { … … 675 661 getCallArg( deref, 0 ) = unqExpr; 676 662 addDeref.insert( unqExpr->get_id() ); 677 if ( unqCount[ unqExpr->get_id() ] == 0 ) { // insert destructor after the last use of the unique expression678 stmtsToAdd.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );679 } else { // remember dtors for last instance of unique expr680 dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter;681 }682 663 return deref; 683 664 } -
src/libcfa/iostream.c
r22854f8 rcb91437 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Mar 22 17: 46:06201713 // Update Count : 35 912 // Last Modified On : Wed Mar 22 17:21:23 2017 13 // Update Count : 358 14 14 // 15 15 … … 201 201 forall( dtype ostype, otype T, ttype Params | ostream( ostype ) | writeable( T ) | { ostype * ?|?( ostype *, Params ); } ) 202 202 ostype * ?|?( ostype * os, T arg, Params rest ) { 203 forall( ttype Params ) ostype * prtTuple( T arg, Params rest ) {203 forall( ttype Params ) ostype * prtTuple( ostype * os, T arg, Params rest ) { 204 204 os | arg; // print first argument 205 205 os | rest; // print remaining arguments … … 207 207 } // prtTuple 208 208 sepSetCur( os, sepGetTuple( os ) ); // switch to tuple separator 209 prtTuple( arg, rest );// recursively print tuple209 prtTuple( os, arg, rest ); // recursively print tuple 210 210 sepSetCur( os, sepGet( os ) ); // switch to regular separator 211 211 return os;
Note:
See TracChangeset
for help on using the changeset viewer.