Changeset 21300d7
- Timestamp:
- Jun 12, 2019, 4:06:37 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 462a7c7, d60780c
- Parents:
- aaeacf4 (diff), 6625727 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 12 added
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/iostream.cfa
raaeacf4 r21300d7 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // iostream.c --7 // iostream.cfa -- 8 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Jun 9 16:27:17201913 // Update Count : 8 0312 // Last Modified On : Wed Jun 12 15:00:31 2019 13 // Update Count : 819 14 14 // 15 15 … … 740 740 } // ?|? 741 741 742 istype & ?|?( istype & is, const char * fmt ) { 743 fmt( is, fmt, "" ); 744 return is; 745 } // ?|? 746 747 istype & ?|?( istype & is, char * s ) { 748 fmt( is, "%s", s ); 749 return is; 750 } // ?|? 751 742 752 // manipulators 743 753 istype & ?|?( istype & is, istype & (* manip)( istype & ) ) { … … 767 777 // skip xxx 768 778 if ( ! f.s ) { 769 // printf( "skip %s\n", f.scanset ); 770 fmt( is, f.scanset, "" ); // no input arguments 779 //printf( "skip %s %d\n", f.scanset, f.wd ); 780 if ( f.wd != -1 ) for ( f.wd ) fmt( is, "%*c" ); // no input arguments 781 else fmt( is, f.scanset, "" ); 771 782 return is; 772 783 } // if … … 797 808 } // ?|? 798 809 810 forall( dtype istype | istream( istype ) ) 811 istype & ?|?( istype & is, _Istream_Char f ) { 812 fmt( is, "%*c" ); // argument variable unused 813 return is; 814 } // ?|? 815 799 816 #define InputFMTImpl( T, CODE ) \ 800 817 forall( dtype istype | istream( istype ) ) \ … … 802 819 enum { size = 16 }; \ 803 820 char fmtstr[size]; \ 804 if ( f.wd == -1 || strcmp( CODE, "c" ) == 0 ) { /* ignore width with "c" */\821 if ( f.wd == -1 ) { \ 805 822 snprintf( fmtstr, size, "%%%s%s", f.ignore ? "*" : "", CODE ); \ 806 823 } else { \ … … 812 829 } // ?|? 813 830 814 InputFMTImpl( char, "c" )815 831 InputFMTImpl( signed char, "hhi" ) 816 832 InputFMTImpl( unsigned char, "hhi" ) -
libcfa/src/iostream.hfa
raaeacf4 r21300d7 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jun 8 17:28:44201913 // Update Count : 3 1212 // Last Modified On : Wed Jun 12 13:35:42 2019 13 // Update Count : 331 14 14 // 15 15 … … 155 155 struct _Ostream_Manip { 156 156 T val; // polymorphic base-type 157 unsigned charwd, pc; // width, precision157 unsigned int wd, pc; // width, precision 158 158 char base; // numeric base / floating-point style 159 159 union { … … 180 180 _Ostream_Manip(T) oct( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'o', { .all : 0 } }; } \ 181 181 _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'x', { .all : 0 } }; } \ 182 _Ostream_Manip(T) wd( unsigned charw, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, CODE, { .all : 0 } }; } \183 _Ostream_Manip(T) wd( unsigned charw, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, CODE, { .flags.pc : true } }; } \184 _Ostream_Manip(T) & wd( unsigned charw, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \185 _Ostream_Manip(T) & wd( unsigned charw, unsigned char pc, _Ostream_Manip(T) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \182 _Ostream_Manip(T) wd( unsigned int w, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, CODE, { .all : 0 } }; } \ 183 _Ostream_Manip(T) wd( unsigned int w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, CODE, { .flags.pc : true } }; } \ 184 _Ostream_Manip(T) & wd( unsigned int w, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \ 185 _Ostream_Manip(T) & wd( unsigned int w, unsigned char pc, _Ostream_Manip(T) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \ 186 186 _Ostream_Manip(T) & left( _Ostream_Manip(T) & fmt ) { fmt.flags.left = true; return fmt; } \ 187 187 _Ostream_Manip(T) & upcase( _Ostream_Manip(T) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; } \ … … 190 190 _Ostream_Manip(T) sign( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, CODE, { .flags.sign : true } }; } \ 191 191 _Ostream_Manip(T) & sign( _Ostream_Manip(T) & fmt ) { fmt.flags.sign = true; return fmt; } \ 192 } \192 } /* distribution */ \ 193 193 forall( dtype ostype | ostream( ostype ) ) { \ 194 194 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \ … … 214 214 _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'a', { .all : 0 } }; } \ 215 215 _Ostream_Manip(T) sci( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'e', { .all : 0 } }; } \ 216 _Ostream_Manip(T) wd( unsigned charw, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, 'f', { .all : 0 } }; } \217 _Ostream_Manip(T) wd( unsigned charw, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'f', { .flags.pc : true } }; } \218 _Ostream_Manip(T) ws( unsigned charw, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'g', { .flags.pc : true } }; } \219 _Ostream_Manip(T) & wd( unsigned charw, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \220 _Ostream_Manip(T) & wd( unsigned charw, unsigned char pc, _Ostream_Manip(T) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \216 _Ostream_Manip(T) wd( unsigned int w, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, 'f', { .all : 0 } }; } \ 217 _Ostream_Manip(T) wd( unsigned int w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'f', { .flags.pc : true } }; } \ 218 _Ostream_Manip(T) ws( unsigned int w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'g', { .flags.pc : true } }; } \ 219 _Ostream_Manip(T) & wd( unsigned int w, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \ 220 _Ostream_Manip(T) & wd( unsigned int w, unsigned char pc, _Ostream_Manip(T) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \ 221 221 _Ostream_Manip(T) & left( _Ostream_Manip(T) & fmt ) { fmt.flags.left = true; return fmt; } \ 222 222 _Ostream_Manip(T) upcase( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'G', { .all : 0 } }; } \ … … 227 227 _Ostream_Manip(T) nodp( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'g', { .flags.nobsdp : true } }; } \ 228 228 _Ostream_Manip(T) & nodp( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \ 229 } \229 } /* distribution */ \ 230 230 forall( dtype ostype | ostream( ostype ) ) { \ 231 231 ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \ … … 239 239 240 240 static inline { 241 _Ostream_Manip(char) bin( char val ) { return (_Ostream_Manip(char))@{ val, 1, 0, 'b', { .all : 0 } }; }242 _Ostream_Manip(char) oct( char val ) { return (_Ostream_Manip(char))@{ val, 1, 0, 'o', { .all : 0 } }; }243 _Ostream_Manip(char) hex( char val ) { return (_Ostream_Manip(char))@{ val, 1, 0, 'x', { .all : 0 } }; }244 _Ostream_Manip(char) wd( unsigned char w, char val ) { return (_Ostream_Manip(char))@{ val, w, 0, 'c', { .all : 0 } }; }245 _Ostream_Manip(char) & wd( unsigned charw, _Ostream_Manip(char) & fmt ) { fmt.wd = w; return fmt; }241 _Ostream_Manip(char) bin( char c ) { return (_Ostream_Manip(char))@{ c, 1, 0, 'b', { .all : 0 } }; } 242 _Ostream_Manip(char) oct( char c ) { return (_Ostream_Manip(char))@{ c, 1, 0, 'o', { .all : 0 } }; } 243 _Ostream_Manip(char) hex( char c ) { return (_Ostream_Manip(char))@{ c, 1, 0, 'x', { .all : 0 } }; } 244 _Ostream_Manip(char) wd( unsigned int w, char c ) { return (_Ostream_Manip(char))@{ c, w, 0, 'c', { .all : 0 } }; } 245 _Ostream_Manip(char) & wd( unsigned int w, _Ostream_Manip(char) & fmt ) { fmt.wd = w; return fmt; } 246 246 _Ostream_Manip(char) & left( _Ostream_Manip(char) & fmt ) { fmt.flags.left = true; return fmt; } 247 247 _Ostream_Manip(char) & upcase( _Ostream_Manip(char) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; } … … 256 256 257 257 static inline { 258 _Ostream_Manip(const char *) bin( const char * val ) { return (_Ostream_Manip(const char *))@{ val, 1, 0, 'b', { .all : 0 } }; }259 _Ostream_Manip(const char *) oct( const char * val ) { return (_Ostream_Manip(const char *))@{ val, 1, 0, 'o', { .all : 0 } }; }260 _Ostream_Manip(const char *) hex( const char * val ) { return (_Ostream_Manip(const char *))@{ val, 1, 0, 'x', { .all : 0 } }; }261 _Ostream_Manip(const char *) wd( unsigned char w, const char * val ) { return (_Ostream_Manip(const char *))@{ val, w, 0, 's', { .all : 0 } }; }262 _Ostream_Manip(const char *) wd( unsigned char w, unsigned char pc, const char * val ) { return (_Ostream_Manip(const char *))@{ val, w, pc, 's', { .flags.pc : true } }; }263 _Ostream_Manip(const char *) & wd( unsigned charw, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; return fmt; }264 _Ostream_Manip(const char *) & wd( unsigned charw, unsigned char pc, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; }258 _Ostream_Manip(const char *) bin( const char * s ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'b', { .all : 0 } }; } 259 _Ostream_Manip(const char *) oct( const char * s ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'o', { .all : 0 } }; } 260 _Ostream_Manip(const char *) hex( const char * s ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'x', { .all : 0 } }; } 261 _Ostream_Manip(const char *) wd( unsigned int w, const char * s ) { return (_Ostream_Manip(const char *))@{ s, w, 0, 's', { .all : 0 } }; } 262 _Ostream_Manip(const char *) wd( unsigned int w, unsigned char pc, const char * s ) { return (_Ostream_Manip(const char *))@{ s, w, pc, 's', { .flags.pc : true } }; } 263 _Ostream_Manip(const char *) & wd( unsigned int w, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; return fmt; } 264 _Ostream_Manip(const char *) & wd( unsigned int w, unsigned char pc, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } 265 265 _Ostream_Manip(const char *) & left( _Ostream_Manip(const char *) & fmt ) { fmt.flags.left = true; return fmt; } 266 266 _Ostream_Manip(const char *) & nobase( _Ostream_Manip(const char *) & fmt ) { fmt.flags.nobsdp = true; return fmt; } … … 316 316 istype & ?|?( istype &, long double _Complex & ); 317 317 318 // Cannot have char & and char * => cstr manipulator319 //istype & ?|?( istype &, char * );318 istype & ?|?( istype &, const char * ); 319 istype & ?|?( istype &, char * ); 320 320 321 321 // manipulators … … 341 341 }; // _Istream_Cstr 342 342 343 static inline _Istream_Cstr skip( const char * scanset ) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; } 344 static inline _Istream_Cstr incl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; } 345 static inline _Istream_Cstr incl( const char * scanset, _Istream_Cstr & fmt ) { fmt.flags.inex = false; return fmt; } 346 static inline _Istream_Cstr excl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; } 347 static inline _Istream_Cstr excl( const char * scanset, _Istream_Cstr & fmt ) { fmt.flags.inex = true; return fmt; } 348 static inline _Istream_Cstr cstr( char * s ) { return (_Istream_Cstr){ s, 0p, -1, { .all : 0 } }; } 349 static inline _Istream_Cstr ignore( const char * s ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; } 350 static inline _Istream_Cstr ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; } 351 static inline _Istream_Cstr wd( unsigned int w, char * s ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; } 352 static inline _Istream_Cstr wd( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; } 353 forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, _Istream_Cstr ); 343 static inline { 344 _Istream_Cstr skip( unsigned int n ) { return (_Istream_Cstr){ 0p, 0p, n, { .all : 0 } }; } 345 _Istream_Cstr skip( const char * scanset ) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; } 346 _Istream_Cstr incl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; } 347 _Istream_Cstr & incl( const char * scanset, _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; } 348 _Istream_Cstr excl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; } 349 _Istream_Cstr & excl( const char * scanset, _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; } 350 _Istream_Cstr ignore( const char * s ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; } 351 _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; } 352 _Istream_Cstr wd( unsigned int w, char * s ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; } 353 _Istream_Cstr & wd( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; } 354 } // distribution 355 forall( dtype istype | istream( istype ) ) istype & ?|?( istype & is, _Istream_Cstr f ); 356 357 struct _Istream_Char { 358 bool ignore; // do not change input argument 359 }; // _Istream_Char 360 361 static inline { 362 _Istream_Char ignore( const char c ) { return (_Istream_Char)@{ true }; } 363 _Istream_Char & ignore( _Istream_Char & fmt ) { fmt.ignore = true; return fmt; } 364 } // distribution 365 forall( dtype istype | istream( istype ) ) istype & ?|?( istype & is, _Istream_Char f ); 354 366 355 367 forall( otype T ) … … 361 373 362 374 #define InputFMTDecl( T ) \ 363 static inline _Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ (T &)val, -1, true }; } \ 364 static inline _Istream_Manip(T) ignore( _Istream_Manip(T) & fmt ) { fmt.ignore = true; return fmt; } \ 365 static inline _Istream_Manip(T) wd( unsigned int w, T & val ) { return (_Istream_Manip(T))@{ val, w, false }; } \ 375 static inline { \ 376 _Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ (T &)val, -1, true }; } \ 377 _Istream_Manip(T) & ignore( _Istream_Manip(T) & fmt ) { fmt.ignore = true; return fmt; } \ 378 _Istream_Manip(T) wdi( unsigned int w, T & val ) { return (_Istream_Manip(T))@{ val, w, false }; } \ 379 _Istream_Manip(T) & wd( unsigned int w, _Istream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \ 380 } /* distribution */ \ 366 381 forall( dtype istype | istream( istype ) ) { \ 367 382 istype & ?|?( istype & is, _Istream_Manip(T) f ); \ 368 383 } // ?|? 369 384 370 InputFMTDecl( char )371 385 InputFMTDecl( signed char ) 372 386 InputFMTDecl( unsigned char ) -
src/AST/Convert.cpp
raaeacf4 r21300d7 2193 2193 2194 2194 int isStringlikeConstantType(const Type *t) { 2195 const Type *referentType = nullptr; 2195 2196 if ( const ArrayType * aty = dynamic_cast< const ArrayType * >( t ) ) { 2196 if ( const BasicType * bty = dynamic_cast< const BasicType * >( aty->base ) ) { 2197 referentType = aty->base; 2198 } else if ( const PointerType * pty = dynamic_cast< const PointerType * >( t ) ) { 2199 referentType = pty->base; 2200 } 2201 if (referentType) { 2202 if ( const BasicType * bty = dynamic_cast< const BasicType * >( referentType ) ) { 2197 2203 if ( bty->kind == BasicType::Kind::Char ) { 2198 2204 return true; … … 2205 2211 virtual void visit( ConstantExpr * old ) override final { 2206 2212 ast::ConstantExpr *rslt = nullptr; 2207 if (isIntlikeConstantType(old->result)) { 2213 if (isStringlikeConstantType(old->result)) { 2214 rslt = new ast::ConstantExpr( 2215 old->location, 2216 GET_ACCEPT_1(result, Type), 2217 old->constant.get_value(), 2218 0, 2219 ast::ConstantExpr::Kind::String 2220 ); 2221 } else if (isIntlikeConstantType(old->result)) { 2208 2222 rslt = new ast::ConstantExpr( 2209 2223 old->location, … … 2219 2233 old->constant.get_value(), 2220 2234 (double) old->constant.get_dval() 2221 );2222 } else if (isStringlikeConstantType(old->result)) {2223 rslt = new ast::ConstantExpr(2224 old->location,2225 GET_ACCEPT_1(result, Type),2226 old->constant.get_value(),2227 0,2228 ast::ConstantExpr::Kind::String2229 2235 ); 2230 2236 } -
src/AST/Node.hpp
raaeacf4 r21300d7 99 99 100 100 /// Mutate a node field (only clones if not equal to existing value) 101 template<typename node_t, typename field_t> 102 const node_t * mutate_field( 103 const node_t * node, 104 typename std::remove_const<typename std::remove_reference<field_t>::type>::type node_t::* field, 105 field_t&& val 106 ) { 101 template<typename node_t, typename field_t, typename assn_t> 102 const node_t * mutate_field( const node_t * node, field_t node_t::* field, assn_t && val ) { 103 // skip mutate if equivalent 107 104 if ( node->*field == val ) return node; 108 105 106 // mutate and return 109 107 node_t * ret = mutate( node ); 110 ret->*field = std::forward< field_t >( val ); 108 ret->*field = std::forward< assn_t >( val ); 109 return ret; 110 } 111 112 /// Mutate a single index of a node field (only clones if not equal to existing value) 113 template<typename node_t, typename coll_t, typename ind_t, typename field_t> 114 const node_t * mutate_field_index( 115 const node_t * node, coll_t node_t::* field, ind_t i, field_t && val 116 ) { 117 // skip mutate if equivalent 118 if ( (node->*field)[i] == val ) return node; 119 120 // mutate and return 121 node_t * ret = mutate( node ); 122 (ret->*field)[i] = std::forward< field_t >( val ); 111 123 return ret; 112 124 } -
src/AST/Print.hpp
raaeacf4 r21300d7 16 16 #pragma once 17 17 18 #include <ios fwd>19 #include <utility> // for forward18 #include <iostream> 19 #include <utility> // for forward 20 20 21 21 #include "AST/Node.hpp" … … 32 32 void printShort( std::ostream & os, const ast::Decl * node, Indenter indent = {} ); 33 33 34 inline void printShort( std::ostream & os, const ast::Decl * node, unsigned int indent ) { 35 printShort( os, node, Indenter{ indent } ); 34 /// Print a collection of items 35 template< typename Coll > 36 void printAll( std::ostream & os, const Coll & c, Indenter indent = {} ) { 37 for ( const auto & i : c ) { 38 if ( ! i ) continue; 39 40 os << indent; 41 print( os, i, indent ); 42 os << std::endl; 43 } 36 44 } 37 45 -
src/AST/porting.md
raaeacf4 r21300d7 299 299 * `openVars` => `open` 300 300 301 `ExplodedActual` => `ExplodedArg` 302 * `ExplodedActual.h` => `ExplodedArg.hpp` 303 301 304 [1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes 302 305 -
src/InitTweak/InitTweak.cc
raaeacf4 r21300d7 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo 3 // 4 // The contents of this file are covered under the licence agreement in the 5 // file "LICENCE" distributed with Cforall. 6 // 7 // InitTweak.cc -- 8 // 9 // Author : Rob Schluntz 10 // Created On : Fri May 13 11:26:36 2016 11 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 10 13:30:00 2019 13 // Update Count : 5 14 // 15 1 16 #include <algorithm> // for find, all_of 2 17 #include <cassert> // for assertf, assert, strict_dynamic_cast … … 4 19 #include <iterator> // for back_insert_iterator, back_inserter 5 20 #include <memory> // for __shared_ptr 21 #include <vector> 6 22 7 23 #include "AST/Expr.hpp" … … 307 323 } 308 324 309 struct CallFinder {310 CallFinder ( const std::list< std::string > & names ) : names( names ) {}325 struct CallFinder_old { 326 CallFinder_old( const std::list< std::string > & names ) : names( names ) {} 311 327 312 328 void postvisit( ApplicationExpr * appExpr ) { … … 331 347 }; 332 348 349 struct CallFinder_new final { 350 std::vector< ast::ptr< ast::Expr > > matches; 351 const std::vector< std::string > names; 352 353 CallFinder_new( std::vector< std::string > && ns ) : matches(), names( std::move(ns) ) {} 354 355 void handleCallExpr( const ast::Expr * expr ) { 356 std::string fname = getFunctionName( expr ); 357 if ( std::find( names.begin(), names.end(), fname ) != names.end() ) { 358 matches.emplace_back( expr ); 359 } 360 } 361 362 void postvisit( const ast::ApplicationExpr * expr ) { handleCallExpr( expr ); } 363 void postvisit( const ast::UntypedExpr * expr ) { handleCallExpr( expr ); } 364 }; 365 333 366 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) { 334 static PassVisitor<CallFinder > finder( std::list< std::string >{ "?{}", "^?{}" } );367 static PassVisitor<CallFinder_old> finder( std::list< std::string >{ "?{}", "^?{}" } ); 335 368 finder.pass.matches = &matches; 336 369 maybeAccept( stmt, finder ); 370 } 371 372 std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt ) { 373 ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } }; 374 maybe_accept( stmt, finder ); 375 return std::move( finder.pass.matches ); 337 376 } 338 377 … … 436 475 } 437 476 477 const ast::ApplicationExpr * isIntrinsicCallExpr( const ast::Expr * expr ) { 478 auto appExpr = dynamic_cast< const ast::ApplicationExpr * >( expr ); 479 if ( ! appExpr ) return nullptr; 480 481 const ast::DeclWithType * func = getCalledFunction( appExpr->func ); 482 assertf( func, 483 "getCalledFunction returned nullptr: %s", toString( appExpr->func ).c_str() ); 484 485 // check for Intrinsic only -- don't want to remove all overridable ctor/dtor because 486 // autogenerated ctor/dtor will call all member dtors, and some members may have a 487 // user-defined dtor 488 return func->linkage == ast::Linkage::Intrinsic ? appExpr : nullptr; 489 } 490 438 491 namespace { 439 492 template <typename Predicate> … … 444 497 return std::all_of( callExprs.begin(), callExprs.end(), pred); 445 498 } 499 500 template <typename Predicate> 501 bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) { 502 std::vector< ast::ptr< ast::Expr > > callExprs = collectCtorDtorCalls( stmt ); 503 return std::all_of( callExprs.begin(), callExprs.end(), pred ); 504 } 446 505 } 447 506 … … 452 511 assert( funcType ); 453 512 return funcType->get_parameters().size() == 1; 513 } 514 return false; 515 }); 516 } 517 518 bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt ) { 519 return allofCtorDtor( stmt, []( const ast::Expr * callExpr ){ 520 if ( const ast::ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 521 const ast::FunctionType * funcType = 522 GenPoly::getFunctionType( appExpr->func->result ); 523 assert( funcType ); 524 return funcType->params.size() == 1; 454 525 } 455 526 return false; -
src/InitTweak/InitTweak.h
raaeacf4 r21300d7 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // RemoveInit.h --7 // InitTweak.h -- 8 8 // 9 9 // Author : Rob Schluntz 10 10 // Created On : Fri May 13 11:26:36 2016 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:30:33 201713 // Update Count : 411 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 10 13:30:00 2019 13 // Update Count : 5 14 14 // 15 15 … … 19 19 #include <memory> // for shared_ptr 20 20 #include <string> // for string, allocator 21 #include <vector> 21 22 22 23 #include "AST/Fwd.hpp" // for AST nodes … … 63 64 /// Non-Null if expr is a call expression whose target function is intrinsic 64 65 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ); 66 const ast::ApplicationExpr * isIntrinsicCallExpr( const ast::Expr * expr); 65 67 66 68 /// True if stmt is a call statement where the function called is intrinsic and takes one parameter. … … 68 70 /// Currently has assertions that make it less than fully general. 69 71 bool isIntrinsicSingleArgCallStmt( Statement * stmt ); 72 bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt ); 70 73 71 74 /// True if stmt is a call statement where the function called is intrinsic. … … 74 77 /// get all Ctor/Dtor call expressions from a Statement 75 78 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ); 79 std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt ); 76 80 77 81 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call -
src/Makefile.in
raaeacf4 r21300d7 195 195 ResolvExpr/CurrentObject.$(OBJEXT) \ 196 196 ResolvExpr/ExplodedActual.$(OBJEXT) \ 197 ResolvExpr/ExplodedArg.$(OBJEXT) \ 197 198 ResolvExpr/FindOpenVars.$(OBJEXT) ResolvExpr/Occurs.$(OBJEXT) \ 198 199 ResolvExpr/PolyCost.$(OBJEXT) \ … … 203 204 ResolvExpr/Resolver.$(OBJEXT) \ 204 205 ResolvExpr/ResolveTypeof.$(OBJEXT) \ 206 ResolvExpr/SatisfyAssertions.$(OBJEXT) \ 205 207 ResolvExpr/SpecCost.$(OBJEXT) \ 206 208 ResolvExpr/TypeEnvironment.$(OBJEXT) \ … … 632 634 ResolvExpr/CurrentObject.cc \ 633 635 ResolvExpr/ExplodedActual.cc \ 636 ResolvExpr/ExplodedArg.cpp \ 634 637 ResolvExpr/FindOpenVars.cc \ 635 638 ResolvExpr/Occurs.cc \ … … 641 644 ResolvExpr/Resolver.cc \ 642 645 ResolvExpr/ResolveTypeof.cc \ 646 ResolvExpr/SatisfyAssertions.cpp \ 643 647 ResolvExpr/SpecCost.cc \ 644 648 ResolvExpr/TypeEnvironment.cc \ … … 893 897 ResolvExpr/ExplodedActual.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 894 898 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 899 ResolvExpr/ExplodedArg.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 900 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 895 901 ResolvExpr/FindOpenVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 896 902 ResolvExpr/$(DEPDIR)/$(am__dirstamp) … … 910 916 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 911 917 ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 918 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 919 ResolvExpr/SatisfyAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 912 920 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 913 921 ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ … … 1273 1281 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CurrentObject.Po@am__quote@ 1274 1282 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ExplodedActual.Po@am__quote@ 1283 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ExplodedArg.Po@am__quote@ 1275 1284 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/FindOpenVars.Po@am__quote@ 1276 1285 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Occurs.Po@am__quote@ … … 1282 1291 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@ 1283 1292 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Resolver.Po@am__quote@ 1293 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/SatisfyAssertions.Po@am__quote@ 1284 1294 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/SpecCost.Po@am__quote@ 1285 1295 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@ -
src/ResolvExpr/AdjustExprType.cc
raaeacf4 r21300d7 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // AdjustExprType .cc --7 // AdjustExprType_old.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 14 14 // 15 15 16 #include "AST/Node.hpp" 17 #include "AST/Pass.hpp" 18 #include "AST/SymbolTable.hpp" 19 #include "AST/Type.hpp" 20 #include "AST/TypeEnvironment.hpp" 16 21 #include "Common/PassVisitor.h" 17 22 #include "SymTab/Indexer.h" // for Indexer … … 22 27 23 28 namespace ResolvExpr { 24 class AdjustExprType : public WithShortCircuiting { 25 public: 26 AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer ); 29 30 namespace { 31 class AdjustExprType_old final : public WithShortCircuiting { 32 public: 33 AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer ); 27 34 void premutate( VoidType * ) { visit_children = false; } 28 35 void premutate( BasicType * ) { visit_children = false; } … … 44 51 Type * postmutate( TypeInstType *aggregateUseType ); 45 52 46 53 private: 47 54 const TypeEnvironment & env; 48 55 const SymTab::Indexer & indexer; 49 56 }; 50 57 51 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 52 PassVisitor<AdjustExprType> adjuster( env, indexer ); 53 Type *newType = type->acceptMutator( adjuster ); 54 type = newType; 55 } 56 57 void adjustExprType( Type *& type ) { 58 TypeEnvironment env; 59 SymTab::Indexer indexer; 60 adjustExprType( type, env, indexer ); 61 } 62 63 AdjustExprType::AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer ) 58 AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer ) 64 59 : env( env ), indexer( indexer ) { 65 60 } 66 61 67 Type * AdjustExprType ::postmutate( ArrayType * arrayType ) {62 Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) { 68 63 PointerType *pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base }; 69 64 arrayType->base = nullptr; … … 72 67 } 73 68 74 Type * AdjustExprType ::postmutate( FunctionType * functionType ) {69 Type * AdjustExprType_old::postmutate( FunctionType * functionType ) { 75 70 return new PointerType{ Type::Qualifiers(), functionType }; 76 71 } 77 72 78 Type * AdjustExprType ::postmutate( TypeInstType * typeInst ) {73 Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) { 79 74 if ( const EqvClass* eqvClass = env.lookup( typeInst->get_name() ) ) { 80 75 if ( eqvClass->data.kind == TypeDecl::Ftype ) { … … 90 85 return typeInst; 91 86 } 87 } // anonymous namespace 88 89 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 90 PassVisitor<AdjustExprType_old> adjuster( env, indexer ); 91 Type *newType = type->acceptMutator( adjuster ); 92 type = newType; 93 } 94 95 void adjustExprType( Type *& type ) { 96 TypeEnvironment env; 97 SymTab::Indexer indexer; 98 adjustExprType( type, env, indexer ); 99 } 100 101 namespace { 102 struct AdjustExprType_new final : public ast::WithShortCircuiting { 103 const ast::TypeEnvironment & tenv; 104 const ast::SymbolTable & symtab; 105 106 AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms ) 107 : tenv( e ), symtab( syms ) {} 108 109 void premutate( const ast::VoidType * ) { visit_children = false; } 110 void premutate( const ast::BasicType * ) { visit_children = false; } 111 void premutate( const ast::PointerType * ) { visit_children = false; } 112 void premutate( const ast::ArrayType * ) { visit_children = false; } 113 void premutate( const ast::FunctionType * ) { visit_children = false; } 114 void premutate( const ast::StructInstType * ) { visit_children = false; } 115 void premutate( const ast::UnionInstType * ) { visit_children = false; } 116 void premutate( const ast::EnumInstType * ) { visit_children = false; } 117 void premutate( const ast::TraitInstType * ) { visit_children = false; } 118 void premutate( const ast::TypeInstType * ) { visit_children = false; } 119 void premutate( const ast::TupleType * ) { visit_children = false; } 120 void premutate( const ast::VarArgsType * ) { visit_children = false; } 121 void premutate( const ast::ZeroType * ) { visit_children = false; } 122 void premutate( const ast::OneType * ) { visit_children = false; } 123 124 const ast::Type * postmutate( const ast::ArrayType * at ) { 125 return new ast::PointerType{ at->base, at->qualifiers }; 126 } 127 128 const ast::Type * postmutate( const ast::FunctionType * ft ) { 129 return new ast::PointerType{ ft }; 130 } 131 132 const ast::Type * postmutate( const ast::TypeInstType * inst ) { 133 // replace known function-type-variables with pointer-to-function 134 if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) { 135 if ( eqvClass->data.kind == ast::TypeVar::Ftype ) { 136 return new ast::PointerType{ inst }; 137 } 138 } else if ( const ast::NamedTypeDecl * ntDecl = symtab.lookupType( inst->name ) ) { 139 if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( ntDecl ) ) { 140 if ( tyDecl->kind == ast::TypeVar::Ftype ) { 141 return new ast::PointerType{ inst }; 142 } 143 } 144 } 145 return inst; 146 } 147 }; 148 } // anonymous namespace 149 150 const ast::Type * adjustExprType( 151 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab 152 ) { 153 ast::Pass<AdjustExprType_new> adjuster{ env, symtab }; 154 return type->accept( adjuster ); 155 } 156 92 157 } // namespace ResolvExpr 93 158 -
src/ResolvExpr/AlternativeFinder.cc
raaeacf4 r21300d7 29 29 #include "AlternativeFinder.h" 30 30 #include "AST/Expr.hpp" 31 #include "AST/SymbolTable.hpp" 31 32 #include "AST/Type.hpp" 32 33 #include "Common/SemanticError.h" // for SemanticError … … 115 116 /// Finds matching alternatives for a function, given a set of arguments 116 117 template<typename OutputIterator> 117 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs & args, OutputIterator out );118 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs_old& args, OutputIterator out ); 118 119 /// Sets up parameter inference for an output alternative 119 120 template< typename OutputIterator > … … 266 267 SemanticError( expr, "No reasonable alternatives for expression " ); 267 268 } 268 if ( mode. resolveAssns || mode.prune ) {269 if ( mode.satisfyAssns || mode.prune ) { 269 270 // trim candidates just to those where the assertions resolve 270 271 // - necessary pre-requisite to pruning … … 592 593 593 594 /// Gets the list of exploded alternatives for this pack 594 const ExplodedActual& getExpl( const ExplodedArgs & args ) const {595 const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const { 595 596 return args[nextArg-1][explAlt]; 596 597 } … … 616 617 /// Instantiates an argument to match a formal, returns false if no results left 617 618 bool instantiateArgument( Type* formalType, Initializer* initializer, 618 const ExplodedArgs & args, std::vector<ArgPack>& results, std::size_t& genStart,619 const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart, 619 620 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 620 621 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) { … … 888 889 template<typename OutputIterator> 889 890 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 890 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {891 FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) { 891 892 OpenVarSet funcOpenVars; 892 893 AssertionSet funcNeed, funcHave; … … 1020 1021 1021 1022 // pre-explode arguments 1022 ExplodedArgs argExpansions;1023 ExplodedArgs_old argExpansions; 1023 1024 argExpansions.reserve( argAlternatives.size() ); 1024 1025 -
src/ResolvExpr/AlternativeFinder.h
raaeacf4 r21300d7 37 37 /// First index is which argument, second index is which alternative for that argument, 38 38 /// third index is which exploded element of that alternative 39 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;39 using ExplodedArgs_old = std::vector< std::vector< ExplodedActual > >; 40 40 41 41 class AlternativeFinder { -
src/ResolvExpr/Candidate.hpp
raaeacf4 r21300d7 30 30 /// A list of unresolved assertions 31 31 using AssertionList = std::vector<AssertionSet::value_type>; 32 33 /// Convenience to merge AssertionList into AssertionSet 34 static inline void mergeAssertionSet( AssertionSet & dst, const AssertionList & src ) { 35 for ( const auto & s : src ) { dst.emplace( s ); } 36 } 32 37 } 33 38 … … 42 47 ast::OpenVarSet open; ///< Open variables for environment 43 48 ast::AssertionList need; ///< Assertions which need to be resolved 49 50 Candidate() : expr(), cost( Cost::zero ), cvtCost( Cost::zero ), env(), open(), need() {} 51 52 Candidate( const ast::Expr * x, const ast::TypeEnvironment & e ) 53 : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {} 54 55 Candidate( const Candidate & o, const ast::Expr * x ) 56 : expr( x ), cost( o.cost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ), 57 need( o.need ) {} 58 59 Candidate( 60 const ast::Expr * x, ast::TypeEnvironment && e, ast::OpenVarSet && o, 61 ast::AssertionSet && n, const Cost & c ) 62 : expr( x ), cost( c ), cvtCost( Cost::zero ), env( std::move( e ) ), open( std::move( o ) ), 63 need( n.begin(), n.end() ) {} 44 64 }; 45 65 … … 49 69 /// List of candidates 50 70 using CandidateList = std::vector< CandidateRef >; 71 72 /// Splice src after dst, clearing src 73 static inline void splice( CandidateList & dst, CandidateList & src ) { 74 dst.reserve( dst.size() + src.size() ); 75 for ( CandidateRef & r : src ) { dst.emplace_back( std::move( r ) ); } 76 src.clear(); 77 } 78 79 /// Splice src before dst 80 static inline void spliceBegin( CandidateList & dst, CandidateList & src ) { 81 splice( src, dst ); 82 dst.swap( src ); 83 } 84 85 /// Sum the cost of a list of candidates 86 static inline Cost sumCost( const CandidateList & candidates ) { 87 Cost total = Cost::zero; 88 for ( const CandidateRef & r : candidates ) { total += r->cost; } 89 return total; 90 } 91 92 /// Holdover behaviour from old `findMinCost` -- xxx -- can maybe be eliminated? 93 static inline void promoteCvtCost( CandidateList & candidates ) { 94 for ( CandidateRef & r : candidates ) { 95 r->cost = r->cvtCost; 96 } 97 } 51 98 52 99 void print( std::ostream & os, const Candidate & cand, Indenter indent = {} ); -
src/ResolvExpr/CandidateFinder.cpp
raaeacf4 r21300d7 16 16 #include "CandidateFinder.hpp" 17 17 18 #include <deque> 19 #include <iterator> // for back_inserter 20 #include <sstream> 21 #include <string> 22 #include <unordered_map> 23 #include <vector> 24 25 #include "Candidate.hpp" 26 #include "CompilationState.h" 27 #include "Cost.h" 28 #include "ExplodedArg.hpp" 29 #include "Resolver.h" 30 #include "SatisfyAssertions.hpp" 31 #include "typeops.h" // for adjustExprType 32 #include "Unify.h" 18 33 #include "AST/Expr.hpp" 34 #include "AST/Node.hpp" 35 #include "AST/Pass.hpp" 36 #include "AST/Print.hpp" 37 #include "AST/SymbolTable.hpp" 38 #include "AST/Type.hpp" 39 #include "SymTab/Mangler.h" 40 #include "Tuples/Tuples.h" // for handleTupleAssignment 41 42 #define PRINT( text ) if ( resolvep ) { text } 19 43 20 44 namespace ResolvExpr { 21 45 46 namespace { 47 48 /// First index is which argument, second is which alternative, third is which exploded element 49 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >; 50 51 /// Returns a list of alternatives with the minimum cost in the given list 52 CandidateList findMinCost( const CandidateList & candidates ) { 53 CandidateList out; 54 Cost minCost = Cost::infinity; 55 for ( const CandidateRef & r : candidates ) { 56 if ( r->cost < minCost ) { 57 minCost = r->cost; 58 out.clear(); 59 out.emplace_back( r ); 60 } else if ( r->cost == minCost ) { 61 out.emplace_back( r ); 62 } 63 } 64 return out; 65 } 66 67 /// Computes conversion cost for a given candidate 68 Cost computeApplicationConversionCost( 69 const CandidateRef & cand, const ast::SymbolTable & symtab 70 ) { 71 #warning unimplemented 72 (void)cand; (void)symtab; 73 assert(false); 74 return Cost::infinity; 75 } 76 77 /// Actually visits expressions to find their candidate interpretations 78 struct Finder final : public ast::WithShortCircuiting { 79 CandidateFinder & selfFinder; 80 const ast::SymbolTable & symtab; 81 CandidateList & candidates; 82 const ast::TypeEnvironment & tenv; 83 ast::ptr< ast::Type > & targetType; 84 85 Finder( CandidateFinder & f ) 86 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ), 87 targetType( f.targetType ) {} 88 89 void previsit( const ast::Node * ) { visit_children = false; } 90 91 /// Convenience to add candidate to list 92 template<typename... Args> 93 void addCandidate( Args &&... args ) { 94 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } ); 95 } 96 97 void postvisit( const ast::ApplicationExpr * applicationExpr ) { 98 addCandidate( applicationExpr, tenv ); 99 } 100 101 /// Builds a list of candidates for a function, storing them in out 102 void makeFunctionCandidates( 103 const CandidateRef & func, const ast::FunctionType * funcType, 104 const ExplodedArgs_new & args, CandidateList & out 105 ) { 106 #warning unimplemented 107 (void)func; (void)funcType; (void)args; (void)out; 108 assert(false); 109 } 110 111 /// Adds implicit struct-conversions to the alternative list 112 void addAnonConversions( const CandidateRef & cand ) { 113 #warning unimplemented 114 (void)cand; 115 assert(false); 116 } 117 118 void postvisit( const ast::UntypedExpr * untypedExpr ) { 119 CandidateFinder funcFinder{ symtab, tenv }; 120 funcFinder.find( untypedExpr->func, ResolvMode::withAdjustment() ); 121 // short-circuit if no candidates 122 if ( funcFinder.candidates.empty() ) return; 123 124 std::vector< CandidateFinder > argCandidates = 125 selfFinder.findSubExprs( untypedExpr->args ); 126 127 // take care of possible tuple assignments 128 // if not tuple assignment, handled as normal function call 129 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates ); 130 131 // find function operators 132 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; 133 CandidateFinder opFinder{ symtab, tenv }; 134 // okay if there aren't any function operations 135 opFinder.find( opExpr, ResolvMode::withoutFailFast() ); 136 PRINT( 137 std::cerr << "known function ops:" << std::endl; 138 print( std::cerr, opFinder.candidates, 1 ); 139 ) 140 141 // pre-explode arguments 142 ExplodedArgs_new argExpansions; 143 for ( const CandidateFinder & args : argCandidates ) { 144 argExpansions.emplace_back(); 145 auto & argE = argExpansions.back(); 146 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); } 147 } 148 149 // Find function matches 150 CandidateList found; 151 SemanticErrorException errors; 152 for ( CandidateRef & func : funcFinder ) { 153 try { 154 PRINT( 155 std::cerr << "working on alternative:" << std::endl; 156 print( std::cerr, *func, 2 ); 157 ) 158 159 // check if the type is a pointer to function 160 const ast::Type * funcResult = func->expr->result->stripReferences(); 161 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) { 162 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 163 CandidateRef newFunc{ new Candidate{ *func } }; 164 newFunc->expr = 165 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 166 makeFunctionCandidates( newFunc, function, argExpansions, found ); 167 } 168 } else if ( 169 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 170 ) { 171 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) { 172 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 173 CandidateRef newFunc{ new Candidate{ *func } }; 174 newFunc->expr = 175 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 176 makeFunctionCandidates( newFunc, function, argExpansions, found ); 177 } 178 } 179 } 180 } catch ( SemanticErrorException & e ) { errors.append( e ); } 181 } 182 183 // Find matches on function operators `?()` 184 if ( ! opFinder.candidates.empty() ) { 185 // add exploded function alternatives to front of argument list 186 std::vector< ExplodedArg > funcE; 187 funcE.reserve( funcFinder.candidates.size() ); 188 for ( const CandidateRef & func : funcFinder ) { 189 funcE.emplace_back( *func, symtab ); 190 } 191 argExpansions.emplace_front( std::move( funcE ) ); 192 193 for ( const CandidateRef & op : opFinder ) { 194 try { 195 // check if type is pointer-to-function 196 const ast::Type * opResult = op->expr->result->stripReferences(); 197 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) { 198 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 199 CandidateRef newOp{ new Candidate{ *op} }; 200 newOp->expr = 201 referenceToRvalueConversion( newOp->expr, newOp->cost ); 202 makeFunctionCandidates( newOp, function, argExpansions, found ); 203 } 204 } 205 } catch ( SemanticErrorException & e ) { errors.append( e ); } 206 } 207 } 208 209 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 210 // candidates 211 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } 212 213 // Compute conversion costs 214 for ( CandidateRef & withFunc : found ) { 215 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab ); 216 217 PRINT( 218 auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >(); 219 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 220 auto function = pointer->base.strict_as< ast::FunctionType >(); 221 222 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 223 std::cerr << "parameters are:" << std::endl; 224 ast::printAll( std::cerr, function->params, 2 ); 225 std::cerr << "arguments are:" << std::endl; 226 ast::printAll( std::cerr, appExpr->args, 2 ); 227 std::cerr << "bindings are:" << std::endl; 228 ast::print( std::cerr, withFunc->env, 2 ); 229 std::cerr << "cost is: " << withFunc->cost << std::endl; 230 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 231 ) 232 233 if ( cvtCost != Cost::infinity ) { 234 withFunc->cvtCost = cvtCost; 235 candidates.emplace_back( std::move( withFunc ) ); 236 } 237 } 238 found = std::move( candidates ); 239 240 // use a new list so that candidates are not examined by addAnonConversions twice 241 CandidateList winners = findMinCost( found ); 242 promoteCvtCost( winners ); 243 244 // function may return a struct/union value, in which case we need to add candidates 245 // for implicit conversions to each of the anonymous members, which must happen after 246 // `findMinCost`, since anon conversions are never the cheapest 247 for ( const CandidateRef & c : winners ) { 248 addAnonConversions( c ); 249 } 250 spliceBegin( candidates, winners ); 251 252 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 253 // If resolution is unsuccessful with a target type, try again without, since it 254 // will sometimes succeed when it wouldn't with a target type binding. 255 // For example: 256 // forall( otype T ) T & ?[]( T *, ptrdiff_t ); 257 // const char * x = "hello world"; 258 // unsigned char ch = x[0]; 259 // Fails with simple return type binding (xxx -- check this!) as follows: 260 // * T is bound to unsigned char 261 // * (x: const char *) is unified with unsigned char *, which fails 262 // xxx -- fix this better 263 targetType = nullptr; 264 postvisit( untypedExpr ); 265 } 266 } 267 268 /// true if expression is an lvalue 269 static bool isLvalue( const ast::Expr * x ) { 270 return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() ); 271 } 272 273 void postvisit( const ast::AddressExpr * addressExpr ) { 274 CandidateFinder finder{ symtab, tenv }; 275 finder.find( addressExpr->arg ); 276 for ( CandidateRef & r : finder.candidates ) { 277 if ( ! isLvalue( r->expr ) ) continue; 278 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } ); 279 } 280 } 281 282 void postvisit( const ast::LabelAddressExpr * labelExpr ) { 283 addCandidate( labelExpr, tenv ); 284 } 285 286 void postvisit( const ast::CastExpr * castExpr ) { 287 #warning unimplemented 288 (void)castExpr; 289 assert(false); 290 } 291 292 void postvisit( const ast::VirtualCastExpr * castExpr ) { 293 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." ); 294 CandidateFinder finder{ symtab, tenv }; 295 // don't prune here, all alternatives guaranteed to have same type 296 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 297 for ( CandidateRef & r : finder.candidates ) { 298 addCandidate( 299 *r, new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 300 } 301 } 302 303 void postvisit( const ast::UntypedMemberExpr * memberExpr ) { 304 #warning unimplemented 305 (void)memberExpr; 306 assert(false); 307 } 308 309 void postvisit( const ast::MemberExpr * memberExpr ) { 310 addCandidate( memberExpr, tenv ); 311 } 312 313 void postvisit( const ast::NameExpr * variableExpr ) { 314 #warning unimplemented 315 (void)variableExpr; 316 assert(false); 317 } 318 319 void postvisit( const ast::VariableExpr * variableExpr ) { 320 // not sufficient to just pass `variableExpr` here, type might have changed since 321 // creation 322 addCandidate( 323 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 324 } 325 326 void postvisit( const ast::ConstantExpr * constantExpr ) { 327 addCandidate( constantExpr, tenv ); 328 } 329 330 void postvisit( const ast::SizeofExpr * sizeofExpr ) { 331 #warning unimplemented 332 (void)sizeofExpr; 333 assert(false); 334 } 335 336 void postvisit( const ast::AlignofExpr * alignofExpr ) { 337 #warning unimplemented 338 (void)alignofExpr; 339 assert(false); 340 } 341 342 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) { 343 #warning unimplemented 344 (void)offsetofExpr; 345 assert(false); 346 } 347 348 void postvisit( const ast::OffsetofExpr * offsetofExpr ) { 349 addCandidate( offsetofExpr, tenv ); 350 } 351 352 void postvisit( const ast::OffsetPackExpr * offsetPackExpr ) { 353 addCandidate( offsetPackExpr, tenv ); 354 } 355 356 void postvisit( const ast::LogicalExpr * logicalExpr ) { 357 CandidateFinder finder1{ symtab, tenv }; 358 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() ); 359 if ( finder1.candidates.empty() ) return; 360 361 CandidateFinder finder2{ symtab, tenv }; 362 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 363 if ( finder2.candidates.empty() ) return; 364 365 for ( const CandidateRef & r1 : finder1.candidates ) { 366 for ( const CandidateRef & r2 : finder2.candidates ) { 367 ast::TypeEnvironment env{ r1->env }; 368 env.simpleCombine( r2->env ); 369 ast::OpenVarSet open{ r1->open }; 370 mergeOpenVars( open, r2->open ); 371 ast::AssertionSet need; 372 mergeAssertionSet( need, r1->need ); 373 mergeAssertionSet( need, r2->need ); 374 375 addCandidate( 376 new ast::LogicalExpr{ 377 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 378 std::move( env ), std::move( open ), std::move( need ), 379 r1->cost + r2->cost ); 380 } 381 } 382 } 383 384 void postvisit( const ast::ConditionalExpr * conditionalExpr ) { 385 // candidates for condition 386 CandidateFinder finder1{ symtab, tenv }; 387 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() ); 388 if ( finder1.candidates.empty() ) return; 389 390 // candidates for true result 391 CandidateFinder finder2{ symtab, tenv }; 392 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 393 if ( finder2.candidates.empty() ) return; 394 395 // candidates for false result 396 CandidateFinder finder3{ symtab, tenv }; 397 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 398 if ( finder3.candidates.empty() ) return; 399 400 for ( const CandidateRef & r1 : finder1.candidates ) { 401 for ( const CandidateRef & r2 : finder2.candidates ) { 402 for ( const CandidateRef & r3 : finder3.candidates ) { 403 ast::TypeEnvironment env{ r1->env }; 404 env.simpleCombine( r2->env ); 405 env.simpleCombine( r3->env ); 406 ast::OpenVarSet open{ r1->open }; 407 mergeOpenVars( open, r2->open ); 408 mergeOpenVars( open, r3->open ); 409 ast::AssertionSet need; 410 mergeAssertionSet( need, r1->need ); 411 mergeAssertionSet( need, r2->need ); 412 mergeAssertionSet( need, r3->need ); 413 ast::AssertionSet have; 414 415 // unify true and false results, then infer parameters to produce new 416 // candidates 417 ast::ptr< ast::Type > common; 418 if ( 419 unify( 420 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 421 common ) 422 ) { 423 #warning unimplemented 424 assert(false); 425 } 426 } 427 } 428 } 429 } 430 431 void postvisit( const ast::CommaExpr * commaExpr ) { 432 ast::TypeEnvironment env{ tenv }; 433 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env ); 434 435 CandidateFinder finder2{ symtab, env }; 436 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); 437 438 for ( const CandidateRef & r2 : finder2.candidates ) { 439 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } ); 440 } 441 } 442 443 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) { 444 addCandidate( ctorExpr, tenv ); 445 } 446 447 void postvisit( const ast::ConstructorExpr * ctorExpr ) { 448 CandidateFinder finder{ symtab, tenv }; 449 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() ); 450 for ( CandidateRef & r : finder.candidates ) { 451 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } ); 452 } 453 } 454 455 void postvisit( const ast::RangeExpr * rangeExpr ) { 456 // resolve low and high, accept candidates where low and high types unify 457 CandidateFinder finder1{ symtab, tenv }; 458 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() ); 459 if ( finder1.candidates.empty() ) return; 460 461 CandidateFinder finder2{ symtab, tenv }; 462 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 463 if ( finder2.candidates.empty() ) return; 464 465 for ( const CandidateRef & r1 : finder1.candidates ) { 466 for ( const CandidateRef & r2 : finder2.candidates ) { 467 ast::TypeEnvironment env{ r1->env }; 468 env.simpleCombine( r2->env ); 469 ast::OpenVarSet open{ r1->open }; 470 mergeOpenVars( open, r2->open ); 471 ast::AssertionSet need; 472 mergeAssertionSet( need, r1->need ); 473 mergeAssertionSet( need, r2->need ); 474 ast::AssertionSet have; 475 476 ast::ptr< ast::Type > common; 477 if ( 478 unify( 479 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 480 common ) 481 ) { 482 ast::RangeExpr * newExpr = 483 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 484 newExpr->result = common ? common : r1->expr->result; 485 486 #warning unimplemented 487 assert(false); 488 } 489 } 490 } 491 } 492 493 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 494 std::vector< CandidateFinder > subCandidates = 495 selfFinder.findSubExprs( tupleExpr->exprs ); 496 std::vector< CandidateList > possibilities; 497 combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) ); 498 499 for ( const CandidateList & subs : possibilities ) { 500 std::vector< ast::ptr< ast::Expr > > exprs; 501 exprs.reserve( subs.size() ); 502 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); } 503 504 ast::TypeEnvironment env; 505 ast::OpenVarSet open; 506 ast::AssertionSet need; 507 for ( const CandidateRef & sub : subs ) { 508 env.simpleCombine( sub->env ); 509 mergeOpenVars( open, sub->open ); 510 mergeAssertionSet( need, sub->need ); 511 } 512 513 addCandidate( 514 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) }, 515 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) ); 516 } 517 } 518 519 void postvisit( const ast::TupleExpr * tupleExpr ) { 520 addCandidate( tupleExpr, tenv ); 521 } 522 523 void postvisit( const ast::TupleIndexExpr * tupleExpr ) { 524 addCandidate( tupleExpr, tenv ); 525 } 526 527 void postvisit( const ast::TupleAssignExpr * tupleExpr ) { 528 addCandidate( tupleExpr, tenv ); 529 } 530 531 void postvisit( const ast::UniqueExpr * unqExpr ) { 532 CandidateFinder finder{ symtab, tenv }; 533 finder.find( unqExpr->expr, ResolvMode::withAdjustment() ); 534 for ( CandidateRef & r : finder.candidates ) { 535 // ensure that the the id is passed on so that the expressions are "linked" 536 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } ); 537 } 538 } 539 540 void postvisit( const ast::StmtExpr * stmtExpr ) { 541 #warning unimplemented 542 (void)stmtExpr; 543 assert(false); 544 } 545 546 void postvisit( const ast::UntypedInitExpr * initExpr ) { 547 #warning unimplemented 548 (void)initExpr; 549 assert(false); 550 } 551 552 void postvisit( const ast::InitExpr * ) { 553 assertf( false, "CandidateFinder should never see a resolved InitExpr." ); 554 } 555 556 void postvisit( const ast::DeletedExpr * ) { 557 assertf( false, "CandidateFinder should never see a DeletedExpr." ); 558 } 559 560 void postvisit( const ast::GenericExpr * ) { 561 assertf( false, "_Generic is not yet supported." ); 562 } 563 }; 564 565 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 566 /// return type. Skips ambiguous candidates. 567 CandidateList pruneCandidates( CandidateList & candidates ) { 568 struct PruneStruct { 569 CandidateRef candidate; 570 bool ambiguous; 571 572 PruneStruct() = default; 573 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {} 574 }; 575 576 // find lowest-cost candidate for each type 577 std::unordered_map< std::string, PruneStruct > selected; 578 for ( CandidateRef & candidate : candidates ) { 579 std::string mangleName; 580 { 581 ast::ptr< ast::Type > newType = candidate->expr->result; 582 candidate->env.apply( newType ); 583 mangleName = Mangle::mangle( newType ); 584 } 585 586 auto found = selected.find( mangleName ); 587 if ( found != selected.end() ) { 588 if ( candidate->cost < found->second.candidate->cost ) { 589 PRINT( 590 std::cerr << "cost " << candidate->cost << " beats " 591 << found->second.candidate->cost << std::endl; 592 ) 593 594 found->second = PruneStruct{ candidate }; 595 } else if ( candidate->cost == found->second.candidate->cost ) { 596 // if one of the candidates contains a deleted identifier, can pick the other, 597 // since deleted expressions should not be ambiguous if there is another option 598 // that is at least as good 599 if ( findDeletedExpr( candidate->expr ) ) { 600 // do nothing 601 PRINT( std::cerr << "candidate is deleted" << std::endl; ) 602 } else if ( findDeletedExpr( found->second.candidate->expr ) ) { 603 PRINT( std::cerr << "current is deleted" << std::endl; ) 604 found->second = PruneStruct{ candidate }; 605 } else { 606 PRINT( std::cerr << "marking ambiguous" << std::endl; ) 607 found->second.ambiguous = true; 608 } 609 } else { 610 PRINT( 611 std::cerr << "cost " << candidate->cost << " loses to " 612 << found->second.candidate->cost << std::endl; 613 ) 614 } 615 } else { 616 selected.emplace_hint( found, mangleName, candidate ); 617 } 618 } 619 620 // report unambiguous min-cost candidates 621 CandidateList out; 622 for ( auto & target : selected ) { 623 if ( target.second.ambiguous ) continue; 624 625 CandidateRef cand = target.second.candidate; 626 627 ast::ptr< ast::Type > newResult = cand->expr->result; 628 cand->env.applyFree( newResult ); 629 cand->expr = ast::mutate_field( 630 cand->expr.get(), &ast::Expr::result, std::move( newResult ) ); 631 632 out.emplace_back( cand ); 633 } 634 return out; 635 } 636 637 } // anonymous namespace 638 22 639 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) { 23 #warning unimplemented 24 (void)expr; (void)mode; 25 assert(false); 640 // Find alternatives for expression 641 ast::Pass<Finder> finder{ *this }; 642 expr->accept( finder ); 643 644 if ( mode.failFast && candidates.empty() ) { 645 SemanticError( expr, "No reasonable alternatives for expression " ); 646 } 647 648 if ( mode.satisfyAssns || mode.prune ) { 649 // trim candidates to just those where the assertions are satisfiable 650 // - necessary pre-requisite to pruning 651 CandidateList satisfied; 652 std::vector< std::string > errors; 653 for ( auto & candidate : candidates ) { 654 satisfyAssertions( *candidate, symtab, satisfied, errors ); 655 } 656 657 // fail early if none such 658 if ( mode.failFast && satisfied.empty() ) { 659 std::ostringstream stream; 660 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 661 for ( const auto& err : errors ) { 662 stream << err; 663 } 664 SemanticError( expr->location, stream.str() ); 665 } 666 667 // reset candidates 668 candidates = std::move( satisfied ); 669 } 670 671 if ( mode.prune ) { 672 // trim candidates to single best one 673 PRINT( 674 std::cerr << "alternatives before prune:" << std::endl; 675 print( std::cerr, candidates ); 676 ) 677 678 CandidateList pruned = pruneCandidates( candidates ); 679 680 if ( mode.failFast && pruned.empty() ) { 681 std::ostringstream stream; 682 CandidateList winners = findMinCost( candidates ); 683 stream << "Cannot choose between " << winners.size() << " alternatives for " 684 "expression\n"; 685 ast::print( stream, expr ); 686 stream << " Alternatives are:\n"; 687 print( stream, winners, 1 ); 688 SemanticError( expr->location, stream.str() ); 689 } 690 691 auto oldsize = candidates.size(); 692 candidates = std::move( pruned ); 693 694 PRINT( 695 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; 696 ) 697 PRINT( 698 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 699 << std::endl; 700 ) 701 } 702 703 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 704 // adjusted 705 if ( mode.adjust ) { 706 for ( CandidateRef & r : candidates ) { 707 r->expr = ast::mutate_field( 708 r->expr.get(), &ast::Expr::result, 709 adjustExprType( r->expr->result, r->env, symtab ) ); 710 } 711 } 712 713 // Central location to handle gcc extension keyword, etc. for all expressions 714 for ( CandidateRef & r : candidates ) { 715 if ( r->expr->extension != expr->extension ) { 716 r->expr.get_and_mutate()->extension = expr->extension; 717 } 718 } 719 } 720 721 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 722 const std::vector< ast::ptr< ast::Expr > > & xs 723 ) { 724 std::vector< CandidateFinder > out; 725 726 for ( const auto & x : xs ) { 727 out.emplace_back( symtab, env ); 728 out.back().find( x, ResolvMode::withAdjustment() ); 729 730 PRINT( 731 std::cerr << "findSubExprs" << std::endl; 732 print( std::cerr, out.back().candidates ); 733 ) 734 } 735 736 return out; 26 737 } 27 738 -
src/ResolvExpr/CandidateFinder.hpp
raaeacf4 r21300d7 19 19 #include "ResolvMode.h" 20 20 #include "AST/Fwd.hpp" 21 #include "AST/Node.hpp" 21 22 #include "AST/SymbolTable.hpp" 22 23 #include "AST/TypeEnvironment.hpp" … … 29 30 const ast::SymbolTable & symtab; ///< Symbol table to lookup candidates 30 31 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 31 const ast::Type *targetType = nullptr; ///< Target type for resolution32 ast::ptr< ast::Type > targetType = nullptr; ///< Target type for resolution 32 33 33 34 CandidateFinder( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) … … 36 37 /// Fill candidates with feasible resolutions for `expr` 37 38 void find( const ast::Expr * expr, ResolvMode mode = {} ); 39 40 /// Runs new candidate finder on each element in xs, returning the list of finders 41 std::vector< CandidateFinder > findSubExprs( const std::vector< ast::ptr< ast::Expr > > & xs ); 42 43 using value_type = CandidateList::value_type; 44 using iterator = CandidateList::iterator; 45 using const_iterator = CandidateList::const_iterator; 46 47 iterator begin() { return candidates.begin(); } 48 const_iterator begin() const { return candidates.begin(); } 49 50 iterator end() { return candidates.end(); } 51 const_iterator end() const { return candidates.end(); } 38 52 }; 39 53 -
src/ResolvExpr/CurrentObject.cc
raaeacf4 r21300d7 946 946 } 947 947 948 void CurrentObject::setNext( const ast::Designation * designation ) { 948 const Designation * CurrentObject::findNext( const Designation * designation ) { 949 using DesignatorChain = std::deque< ptr< Expr > >; 950 PRINT( std::cerr << "___findNext" << std::endl; ) 951 952 // find all the d's 953 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts; 954 std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes; 955 for ( const Expr * expr : designation->designators ) { 956 PRINT( std::cerr << "____untyped: " << expr << std::endl; ) 957 auto dit = desigAlts.begin(); 958 if ( auto nexpr = dynamic_cast< const NameExpr * >( expr ) ) { 959 for ( const Type * t : curTypes ) { 960 assert( dit != desigAlts.end() ); 961 962 DesignatorChain & d = *dit; 963 PRINT( std::cerr << "____actual: " << t << std::endl; ) 964 if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) { 965 // concatenate identical field names 966 for ( const Decl * mem : refType->lookup( nexpr->name ) ) { 967 if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) { 968 PRINT( std::cerr << "____alt: " << field->type << std::endl; ) 969 DesignatorChain d2 = d; 970 d2.emplace_back( new VariableExpr{ expr->location, field } ); 971 newDesigAlts.emplace_back( std::move( d2 ) ); 972 newTypes.emplace_back( field->type ); 973 } 974 } 975 } 976 977 ++dit; 978 } 979 } else { 980 for ( const Type * t : curTypes ) { 981 assert( dit != desigAlts.end() ); 982 983 DesignatorChain & d = *dit; 984 if ( auto at = dynamic_cast< const ArrayType * >( t ) ) { 985 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; ) 986 d.emplace_back( expr ); 987 newDesigAlts.emplace_back( d ); 988 newTypes.emplace_back( at->base ); 989 } 990 } 991 } 992 993 // reset queue 994 desigAlts = std::move( newDesigAlts ); 995 newDesigAlts.clear(); 996 curTypes = std::move( newTypes ); 997 newTypes.clear(); 998 assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() ); 999 } 1000 1001 if ( desigAlts.size() > 1 ) { 1002 SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") ); 1003 } else if ( desigAlts.empty() ) { 1004 SemanticError( designation, "No reasonable alternatives for designation: " ); 1005 } 1006 1007 DesignatorChain & d = desigAlts.back(); 1008 PRINT( for ( Expression * expr : d ) { 1009 std::cerr << "____desig: " << expr << std::endl; 1010 } ) // for 1011 assertf( ! curTypes.empty(), "empty designator chosen"); 1012 1013 // set new designators 1014 assertf( ! objStack.empty(), "empty object stack when setting designation" ); 1015 Designation * actualDesignation = 1016 new Designation{ designation->location, DesignatorChain{d} }; 1017 objStack.back()->setPosition( d ); // destroys d 1018 return actualDesignation; 1019 } 1020 1021 void CurrentObject::setNext( const Designation * designation ) { 949 1022 PRINT( std::cerr << "____setNext" << designation << std::endl; ) 950 1023 assertf( ! objStack.empty(), "obj stack empty in setNext" ); -
src/ResolvExpr/CurrentObject.h
raaeacf4 r21300d7 111 111 CurrentObject( const CodeLocation & loc, const Type * type ); 112 112 113 /// resolves unresolved designation 114 const Designation * findNext( const Designation * designation ); 113 115 /// sets current position using the resolved designation 114 116 void setNext( const ast::Designation * designation ); -
src/ResolvExpr/ExplodedActual.cc
raaeacf4 r21300d7 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Alternative.h--7 // ExplodedActual.cc -- 8 8 // 9 9 // Author : Aaron B. Moss … … 24 24 } 25 25 } 26 27 // Local Variables: // 28 // tab-width: 4 // 29 // mode: c++ // 30 // compile-command: "make install" // 31 // End: // -
src/ResolvExpr/ExplodedActual.h
raaeacf4 r21300d7 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Alternative.h --7 // ExplodedActual.h -- 8 8 // 9 9 // Author : Aaron B. Moss … … 37 37 }; 38 38 } 39 40 // Local Variables: // 41 // tab-width: 4 // 42 // mode: c++ // 43 // compile-command: "make install" // 44 // End: // -
src/ResolvExpr/ResolvMode.h
raaeacf4 r21300d7 22 22 const bool prune; ///< Prune alternatives to min-cost per return type? [true] 23 23 const bool failFast; ///< Fail on no resulting alternatives? [true] 24 const bool resolveAssns; ///< Resolveassertions? [false]24 const bool satisfyAssns; ///< Satisfy assertions? [false] 25 25 26 26 private: 27 constexpr ResolvMode(bool a, bool p, bool ff, bool ra)28 : adjust(a), prune(p), failFast(ff), resolveAssns(ra) {}27 constexpr ResolvMode(bool a, bool p, bool ff, bool sa) 28 : adjust(a), prune(p), failFast(ff), satisfyAssns(sa) {} 29 29 30 30 public: 31 31 /// Default settings 32 constexpr ResolvMode() : adjust(false), prune(true), failFast(true), resolveAssns(false) {}32 constexpr ResolvMode() : adjust(false), prune(true), failFast(true), satisfyAssns(false) {} 33 33 34 34 /// With adjust flag set; turns array and function types into equivalent pointers … … 43 43 static constexpr ResolvMode withoutFailFast() { return { true, true, false, false }; } 44 44 45 /// The same mode, but with resolveAssns turned on; for top-level calls45 /// The same mode, but with satisfyAssns turned on; for top-level calls 46 46 ResolvMode atTopLevel() const { return { adjust, prune, failFast, true }; } 47 47 }; -
src/ResolvExpr/Resolver.cc
raaeacf4 r21300d7 35 35 #include "AST/Print.hpp" 36 36 #include "AST/SymbolTable.hpp" 37 #include "AST/Type.hpp" 37 38 #include "Common/PassVisitor.h" // for PassVisitor 38 39 #include "Common/SemanticError.h" // for SemanticError … … 956 957 } 957 958 }; 958 959 /// Check if this expression is or includes a deleted expression 960 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 961 ast::Pass<DeleteFinder_new> finder; 962 expr->accept( finder ); 963 return finder.pass.delExpr; 964 } 965 959 } // anonymous namespace 960 961 /// Check if this expression is or includes a deleted expression 962 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 963 ast::Pass<DeleteFinder_new> finder; 964 expr->accept( finder ); 965 return finder.pass.delExpr; 966 } 967 968 namespace { 966 969 /// always-accept candidate filter 967 970 bool anyCandidate( const Candidate & ) { return true; } … … 1023 1026 1024 1027 // promote candidate.cvtCost to .cost 1025 for ( CandidateRef & cand : winners ) { 1026 cand->cost = cand->cvtCost; 1027 } 1028 promoteCvtCost( winners ); 1028 1029 1029 1030 // produce ambiguous errors, if applicable … … 1099 1100 StripCasts_new::strip( expr ); 1100 1101 } 1101 1102 /// Find the expression candidate that is the unique best match for `untyped` in a `void` 1103 /// context. 1104 ast::ptr< ast::Expr > resolveInVoidContext( 1105 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1106 ) { 1107 assertf( expr, "expected a non-null expression" ); 1108 1109 // set up and resolve expression cast to void 1110 ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr }; 1111 CandidateRef choice = findUnfinishedKindExpression( 1112 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); 1113 1114 // a cast expression has either 0 or 1 interpretations (by language rules); 1115 // if 0, an exception has already been thrown, and this code will not run 1116 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 1117 env = std::move( choice->env ); 1118 1119 return castExpr->arg; 1120 } 1121 1102 } // anonymous namespace 1103 1104 1105 ast::ptr< ast::Expr > resolveInVoidContext( 1106 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1107 ) { 1108 assertf( expr, "expected a non-null expression" ); 1109 1110 // set up and resolve expression cast to void 1111 ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr }; 1112 CandidateRef choice = findUnfinishedKindExpression( 1113 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); 1114 1115 // a cast expression has either 0 or 1 interpretations (by language rules); 1116 // if 0, an exception has already been thrown, and this code will not run 1117 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 1118 env = std::move( choice->env ); 1119 1120 return castExpr->arg; 1121 } 1122 1123 namespace { 1122 1124 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1123 1125 /// context. … … 1146 1148 } 1147 1149 1150 /// Resolve `untyped` to the single expression whose candidate is the best match 1151 ast::ptr< ast::Expr > findSingleExpression( 1152 const ast::Expr * untyped, const ast::SymbolTable & symtab 1153 ) { 1154 return findKindExpression( untyped, symtab ); 1155 } 1156 1148 1157 /// Resolve `untyped` to the single expression whose candidate is the best match for the 1149 1158 /// given type. … … 1152 1161 ) { 1153 1162 assert( untyped && type ); 1154 const ast::Expr *castExpr = new ast::CastExpr{ untyped->location, untyped, type };1155 ast::ptr< ast::Expr > newExpr = find KindExpression( castExpr, symtab );1163 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped->location, untyped, type }; 1164 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab ); 1156 1165 removeExtraneousCast( newExpr, symtab ); 1157 1166 return newExpr; … … 1189 1198 return false; 1190 1199 } 1200 1201 /// Advance a type itertor to the next mutex parameter 1202 template<typename Iter> 1203 inline bool nextMutex( Iter & it, const Iter & end ) { 1204 while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; } 1205 return it != end; 1206 } 1191 1207 } 1192 1208 … … 1213 1229 void previsit( const ast::PointerType * ); 1214 1230 1215 const ast::ExprStmt * previsit( const ast::ExprStmt * );1216 const ast::AsmExpr * previsit( const ast::AsmExpr * );1217 const ast::AsmStmt * previsit( const ast::AsmStmt * );1218 const ast::IfStmt * previsit( const ast::IfStmt * );1219 const ast::WhileStmt * previsit( const ast::WhileStmt * );1220 const ast::ForStmt * previsit( const ast::ForStmt * );1221 const ast::SwitchStmt * previsit( const ast::SwitchStmt * );1222 const ast::CaseStmt * previsit( const ast::CaseStmt * );1223 const ast::BranchStmt * previsit( const ast::BranchStmt * );1224 const ast::ReturnStmt * previsit( const ast::ReturnStmt * );1225 const ast::ThrowStmt * previsit( const ast::ThrowStmt * );1226 const ast::CatchStmt * previsit( const ast::CatchStmt * );1227 voidprevisit( const ast::WaitForStmt * );1228 1229 const ast::SingleInit * previsit( const ast::SingleInit * );1230 const ast::ListInit * previsit( const ast::ListInit * );1231 voidprevisit( const ast::ConstructorInit * );1231 const ast::ExprStmt * previsit( const ast::ExprStmt * ); 1232 const ast::AsmExpr * previsit( const ast::AsmExpr * ); 1233 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 1234 const ast::IfStmt * previsit( const ast::IfStmt * ); 1235 const ast::WhileStmt * previsit( const ast::WhileStmt * ); 1236 const ast::ForStmt * previsit( const ast::ForStmt * ); 1237 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 1238 const ast::CaseStmt * previsit( const ast::CaseStmt * ); 1239 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 1240 const ast::ReturnStmt * previsit( const ast::ReturnStmt * ); 1241 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 1242 const ast::CatchStmt * previsit( const ast::CatchStmt * ); 1243 const ast::WaitForStmt * previsit( const ast::WaitForStmt * ); 1244 1245 const ast::SingleInit * previsit( const ast::SingleInit * ); 1246 const ast::ListInit * previsit( const ast::ListInit * ); 1247 const ast::ConstructorInit * previsit( const ast::ConstructorInit * ); 1232 1248 }; 1233 1249 … … 1381 1397 "expression." ); 1382 1398 1383 const ast::Expr *untyped =1399 ast::ptr< ast::Expr > untyped = 1384 1400 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1385 ast::ptr< ast::Expr > newExpr = find KindExpression( untyped, symtab );1401 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab ); 1386 1402 1387 1403 // case condition cannot have a cast in C, so it must be removed here, regardless of … … 1401 1417 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 1402 1418 // computed goto argument is void* 1419 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} }; 1403 1420 branchStmt = ast::mutate_field( 1404 1421 branchStmt, &ast::BranchStmt::computedTarget, 1405 findSingleExpression( 1406 branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 1407 symtab ) ); 1422 findSingleExpression( branchStmt->computedTarget, target, symtab ) ); 1408 1423 } 1409 1424 return branchStmt; … … 1445 1460 } 1446 1461 1447 void Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1448 #warning unimplemented; Resolver port in progress 1449 (void)stmt; 1450 assert(false); 1462 const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1463 visit_children = false; 1464 1465 // Resolve all clauses first 1466 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) { 1467 const ast::WaitForStmt::Clause & clause = stmt->clauses[i]; 1468 1469 ast::TypeEnvironment env; 1470 CandidateFinder funcFinder{ symtab, env }; 1471 1472 // Find all candidates for a function in canonical form 1473 funcFinder.find( clause.target.func, ResolvMode::withAdjustment() ); 1474 1475 if ( funcFinder.candidates.empty() ) { 1476 stringstream ss; 1477 ss << "Use of undeclared indentifier '"; 1478 ss << clause.target.func.strict_as< ast::NameExpr >()->name; 1479 ss << "' in call to waitfor"; 1480 SemanticError( stmt->location, ss.str() ); 1481 } 1482 1483 if ( clause.target.args.empty() ) { 1484 SemanticError( stmt->location, 1485 "Waitfor clause must have at least one mutex parameter"); 1486 } 1487 1488 // Find all alternatives for all arguments in canonical form 1489 std::vector< CandidateFinder > argFinders = 1490 funcFinder.findSubExprs( clause.target.args ); 1491 1492 // List all combinations of arguments 1493 std::vector< CandidateList > possibilities; 1494 combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) ); 1495 1496 // For every possible function: 1497 // * try matching the arguments to the parameters, not the other way around because 1498 // more arguments than parameters 1499 CandidateList funcCandidates; 1500 std::vector< CandidateList > argsCandidates; 1501 SemanticErrorException errors; 1502 for ( CandidateRef & func : funcFinder.candidates ) { 1503 try { 1504 auto pointerType = dynamic_cast< const ast::PointerType * >( 1505 func->expr->result->stripReferences() ); 1506 if ( ! pointerType ) { 1507 SemanticError( stmt->location, func->expr->result.get(), 1508 "candidate not viable: not a pointer type\n" ); 1509 } 1510 1511 auto funcType = pointerType->base.as< ast::FunctionType >(); 1512 if ( ! funcType ) { 1513 SemanticError( stmt->location, func->expr->result.get(), 1514 "candidate not viable: not a function type\n" ); 1515 } 1516 1517 { 1518 auto param = funcType->params.begin(); 1519 auto paramEnd = funcType->params.end(); 1520 1521 if( ! nextMutex( param, paramEnd ) ) { 1522 SemanticError( stmt->location, funcType, 1523 "candidate function not viable: no mutex parameters\n"); 1524 } 1525 } 1526 1527 CandidateRef func2{ new Candidate{ *func } }; 1528 // strip reference from function 1529 func2->expr = referenceToRvalueConversion( func->expr, func2->cost ); 1530 1531 // Each argument must be matched with a parameter of the current candidate 1532 for ( auto & argsList : possibilities ) { 1533 try { 1534 // Declare data structures needed for resolution 1535 ast::OpenVarSet open; 1536 ast::AssertionSet need, have; 1537 ast::TypeEnvironment resultEnv{ func->env }; 1538 // Add all type variables as open so that those not used in the 1539 // parameter list are still considered open 1540 resultEnv.add( funcType->forall ); 1541 1542 // load type variables from arguments into one shared space 1543 for ( auto & arg : argsList ) { 1544 resultEnv.simpleCombine( arg->env ); 1545 } 1546 1547 // Make sure we don't widen any existing bindings 1548 resultEnv.forbidWidening(); 1549 1550 // Find any unbound type variables 1551 resultEnv.extractOpenVars( open ); 1552 1553 auto param = funcType->params.begin(); 1554 auto paramEnd = funcType->params.end(); 1555 1556 unsigned n_mutex_param = 0; 1557 1558 // For every argument of its set, check if it matches one of the 1559 // parameters. The order is important 1560 for ( auto & arg : argsList ) { 1561 // Ignore non-mutex arguments 1562 if ( ! nextMutex( param, paramEnd ) ) { 1563 // We ran out of parameters but still have arguments. 1564 // This function doesn't match 1565 SemanticError( stmt->location, funcType, 1566 toString("candidate function not viable: too many mutex " 1567 "arguments, expected ", n_mutex_param, "\n" ) ); 1568 } 1569 1570 ++n_mutex_param; 1571 1572 // Check if the argument matches the parameter type in the current 1573 // scope 1574 ast::ptr< ast::Type > paramType = (*param)->get_type(); 1575 if ( 1576 ! unify( 1577 arg->expr->result, paramType, resultEnv, need, have, open, 1578 symtab ) 1579 ) { 1580 // Type doesn't match 1581 stringstream ss; 1582 ss << "candidate function not viable: no known conversion " 1583 "from '"; 1584 ast::print( ss, (*param)->get_type() ); 1585 ss << "' to '"; 1586 ast::print( ss, arg->expr->result ); 1587 ss << "' with env '"; 1588 ast::print( ss, resultEnv ); 1589 ss << "'\n"; 1590 SemanticError( stmt->location, funcType, ss.str() ); 1591 } 1592 1593 ++param; 1594 } 1595 1596 // All arguments match! 1597 1598 // Check if parameters are missing 1599 if ( nextMutex( param, paramEnd ) ) { 1600 do { 1601 ++n_mutex_param; 1602 ++param; 1603 } while ( nextMutex( param, paramEnd ) ); 1604 1605 // We ran out of arguments but still have parameters left; this 1606 // function doesn't match 1607 SemanticError( stmt->location, funcType, 1608 toString( "candidate function not viable: too few mutex " 1609 "arguments, expected ", n_mutex_param, "\n" ) ); 1610 } 1611 1612 // All parameters match! 1613 1614 // Finish the expressions to tie in proper environments 1615 finishExpr( func2->expr, resultEnv ); 1616 for ( CandidateRef & arg : argsList ) { 1617 finishExpr( arg->expr, resultEnv ); 1618 } 1619 1620 // This is a match, store it and save it for later 1621 funcCandidates.emplace_back( std::move( func2 ) ); 1622 argsCandidates.emplace_back( std::move( argsList ) ); 1623 1624 } catch ( SemanticErrorException & e ) { 1625 errors.append( e ); 1626 } 1627 } 1628 } catch ( SemanticErrorException & e ) { 1629 errors.append( e ); 1630 } 1631 } 1632 1633 // Make sure correct number of arguments 1634 if( funcCandidates.empty() ) { 1635 SemanticErrorException top( stmt->location, 1636 "No alternatives for function in call to waitfor" ); 1637 top.append( errors ); 1638 throw top; 1639 } 1640 1641 if( argsCandidates.empty() ) { 1642 SemanticErrorException top( stmt->location, 1643 "No alternatives for arguments in call to waitfor" ); 1644 top.append( errors ); 1645 throw top; 1646 } 1647 1648 if( funcCandidates.size() > 1 ) { 1649 SemanticErrorException top( stmt->location, 1650 "Ambiguous function in call to waitfor" ); 1651 top.append( errors ); 1652 throw top; 1653 } 1654 if( argsCandidates.size() > 1 ) { 1655 SemanticErrorException top( stmt->location, 1656 "Ambiguous arguments in call to waitfor" ); 1657 top.append( errors ); 1658 throw top; 1659 } 1660 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 1661 1662 // build new clause 1663 ast::WaitForStmt::Clause clause2; 1664 1665 clause2.target.func = funcCandidates.front()->expr; 1666 1667 clause2.target.args.reserve( clause.target.args.size() ); 1668 for ( auto arg : argsCandidates.front() ) { 1669 clause2.target.args.emplace_back( std::move( arg->expr ) ); 1670 } 1671 1672 // Resolve the conditions as if it were an IfStmt, statements normally 1673 clause2.cond = findSingleExpression( clause.cond, symtab ); 1674 clause2.stmt = clause.stmt->accept( *visitor ); 1675 1676 // set results into stmt 1677 auto n = mutate( stmt ); 1678 n->clauses[i] = std::move( clause2 ); 1679 stmt = n; 1680 } 1681 1682 if ( stmt->timeout.stmt ) { 1683 // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally 1684 ast::WaitForStmt::Timeout timeout2; 1685 1686 ast::ptr< ast::Type > target = 1687 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1688 timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab ); 1689 timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab ); 1690 timeout2.stmt = stmt->timeout.stmt->accept( *visitor ); 1691 1692 // set results into stmt 1693 auto n = mutate( stmt ); 1694 n->timeout = std::move( timeout2 ); 1695 stmt = n; 1696 } 1697 1698 if ( stmt->orElse.stmt ) { 1699 // resolve the condition like IfStmt, stmts normally 1700 ast::WaitForStmt::OrElse orElse2; 1701 1702 orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab ); 1703 orElse2.stmt = stmt->orElse.stmt->accept( *visitor ); 1704 1705 // set results into stmt 1706 auto n = mutate( stmt ); 1707 n->orElse = std::move( orElse2 ); 1708 stmt = n; 1709 } 1710 1711 return stmt; 1451 1712 } 1452 1713 … … 1457 1718 // resolve initialization using the possibilities as determined by the `currentObject` 1458 1719 // cursor. 1459 ast:: Expr *untyped = new ast::UntypedInitExpr{1720 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{ 1460 1721 singleInit->location, singleInit->value, currentObject.getOptions() }; 1461 ast::ptr<ast::Expr> newExpr = find KindExpression( untyped, symtab );1722 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab ); 1462 1723 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 1463 1724 … … 1510 1771 // iterate designations and initializers in pairs, moving the cursor to the current 1511 1772 // designated object and resolving the initializer against that object 1512 #warning unimplemented; Resolver port in progress 1513 assert(false); 1514 } 1773 listInit = ast::mutate_field_index( 1774 listInit, &ast::ListInit::designations, i, 1775 currentObject.findNext( listInit->designations[i] ) ); 1776 listInit = ast::mutate_field_index( 1777 listInit, &ast::ListInit::initializers, i, 1778 listInit->initializers[i]->accept( *visitor ) ); 1779 } 1780 1781 // move cursor out of brace-enclosed initializer-list 1782 currentObject.exitListInit(); 1515 1783 1516 1784 visit_children = false; … … 1518 1786 } 1519 1787 1520 void Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) { 1521 #warning unimplemented; Resolver port in progress 1522 (void)ctorInit; 1523 assert(false); 1788 const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) { 1789 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor ); 1790 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor ); 1791 1792 // found a constructor - can get rid of C-style initializer 1793 // xxx - Rob suggests this field is dead code 1794 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr ); 1795 1796 // intrinsic single-parameter constructors and destructors do nothing. Since this was 1797 // implicitly generated, there's no way for it to have side effects, so get rid of it to 1798 // clean up generated code 1799 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) { 1800 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr ); 1801 } 1802 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) { 1803 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr ); 1804 } 1805 1806 return ctorInit; 1524 1807 } 1525 1808 -
src/ResolvExpr/Resolver.h
raaeacf4 r21300d7 17 17 18 18 #include <list> // for list 19 #include <AST/Node.hpp> // for ptr 19 20 #include "AST/Node.hpp" // for ptr 20 21 21 22 class ConstructorInit; … … 29 30 namespace ast { 30 31 class Decl; 32 class DeletedExpr; 33 class SymbolTable; 34 class TypeEnvironment; 31 35 } // namespace ast 32 36 … … 48 52 /// Checks types and binds syntactic constructs to typed representations 49 53 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ); 54 /// Searches expr and returns the first DeletedExpr found, otherwise nullptr 55 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ); 56 /// Find the expression candidate that is the unique best match for `untyped` in a `void` 57 /// context. 58 ast::ptr< ast::Expr > resolveInVoidContext( 59 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env ); 50 60 } // namespace ResolvExpr 51 61 -
src/ResolvExpr/Unify.cc
raaeacf4 r21300d7 1143 1143 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1144 1144 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1145 ast::OpenVarSet & open, const ast::SymbolTable & symtab 1146 ) { 1147 ast::ptr<ast::Type> common; 1148 return unify( type1, type2, env, need, have, open, symtab, common ); 1149 } 1150 1151 bool unify( 1152 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1153 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1145 1154 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common 1146 1155 ) { -
src/ResolvExpr/Unify.h
raaeacf4 r21300d7 72 72 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 73 73 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 74 ast::OpenVarSet & open, const ast::SymbolTable & symtab ); 75 76 bool unify( 77 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 78 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 74 79 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common ); 75 80 -
src/ResolvExpr/module.mk
raaeacf4 r21300d7 26 26 ResolvExpr/CurrentObject.cc \ 27 27 ResolvExpr/ExplodedActual.cc \ 28 ResolvExpr/ExplodedArg.cpp \ 28 29 ResolvExpr/FindOpenVars.cc \ 29 30 ResolvExpr/Occurs.cc \ … … 35 36 ResolvExpr/Resolver.cc \ 36 37 ResolvExpr/ResolveTypeof.cc \ 38 ResolvExpr/SatisfyAssertions.cpp \ 37 39 ResolvExpr/SpecCost.cc \ 38 40 ResolvExpr/TypeEnvironment.cc \ -
src/ResolvExpr/typeops.h
raaeacf4 r21300d7 71 71 } // while 72 72 } 73 74 /// Replaces array types with equivalent pointer, and function types with a pointer-to-function 75 const ast::Type * adjustExprType( 76 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab ); 73 77 74 78 // in CastCost.cc -
src/Tuples/Explode.h
raaeacf4 r21300d7 19 19 #include <utility> // for forward 20 20 21 #include "AST/Expr.hpp" 21 22 #include "ResolvExpr/Alternative.h" // for Alternative, AltList 23 #include "ResolvExpr/Candidate.hpp" // for Candidate, CandidateList 22 24 #include "ResolvExpr/ExplodedActual.h" // for ExplodedActual 25 #include "ResolvExpr/ExplodedArg.hpp" // for ExplodedArg 23 26 #include "SynTree/Expression.h" // for Expression, UniqueExpr, AddressExpr 24 27 #include "SynTree/Type.h" // for TupleType, Type 25 28 #include "Tuples.h" // for maybeImpure 29 30 namespace ast { 31 class SymbolTable; 32 } 26 33 27 34 namespace SymTab { … … 130 137 explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign ); 131 138 } 139 140 /// helper function used by explode 141 template< typename Output > 142 void explodeUnique( 143 const ast::Expr * expr, const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, 144 Output && out, bool isTupleAssign 145 ) { 146 #warning unimplemented 147 (void)expr; (void)arg; (void)symtab; (void)out; (void)isTupleAssign; 148 assert(false); 149 } 150 151 /// expands a tuple-valued candidate into multiple candidates, each with a non-tuple type 152 template< typename Output > 153 void explode( 154 const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out, 155 bool isTupleAssign = false 156 ) { 157 explodeUnique( arg.expr, arg, symtab, std::forward< Output >( out ), isTupleAssign ); 158 } 159 132 160 } // namespace Tuples 133 161 -
src/Tuples/TupleAssignment.cc
raaeacf4 r21300d7 377 377 } 378 378 } 379 380 void handleTupleAssignment( 381 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 382 std::vector< ResolvExpr::CandidateFinder > & args 383 ) { 384 #warning unimplmented 385 (void)finder; (void)assign; (void)args; 386 assert(false); 387 } 379 388 } // namespace Tuples 380 389 -
src/Tuples/Tuples.h
raaeacf4 r21300d7 26 26 27 27 #include "ResolvExpr/AlternativeFinder.h" 28 #include "ResolvExpr/CandidateFinder.hpp" 28 29 29 30 namespace Tuples { … … 31 32 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, 32 33 std::vector< ResolvExpr::AlternativeFinder >& args ); 34 void handleTupleAssignment( 35 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 36 std::vector< ResolvExpr::CandidateFinder > & args ); 33 37 34 38 // TupleExpansion.cc -
tests/sum.cfa
raaeacf4 r21300d7 11 11 // Created On : Wed May 27 17:56:53 2015 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Sun May 19 11:21:02 201914 // Update Count : 33 013 // Last Modified On : Thu Jun 6 16:18:22 2019 14 // Update Count : 333 15 15 // 16 16 … … 111 111 }; 112 112 GS(int) gs; 113 gs.x = anew( size ); // create array storage for field 113 // FIX ME, resolution problem with anew not picking up the LH type 114 gs.x = (typeof(gs.x))anew( size ); // create array storage for field 114 115 s = 0; v = low; 115 116 for ( int i = 0; i < size; i += 1, v += 1 ) {
Note: See TracChangeset
for help on using the changeset viewer.