Changes in / [21300d7:aaeacf4]
- Files:
-
- 12 deleted
- 30 edited
-
libcfa/src/iostream.cfa (modified) (6 diffs)
-
libcfa/src/iostream.hfa (modified) (11 diffs)
-
src/AST/Convert.cpp (modified) (3 diffs)
-
src/AST/Node.hpp (modified) (1 diff)
-
src/AST/Print.hpp (modified) (2 diffs)
-
src/AST/porting.md (modified) (1 diff)
-
src/InitTweak/InitTweak.cc (modified) (7 diffs)
-
src/InitTweak/InitTweak.h (modified) (5 diffs)
-
src/Makefile.in (modified) (8 diffs)
-
src/ResolvExpr/AdjustExprType.cc (modified) (6 diffs)
-
src/ResolvExpr/AlternativeFinder.cc (modified) (7 diffs)
-
src/ResolvExpr/AlternativeFinder.h (modified) (1 diff)
-
src/ResolvExpr/Candidate.hpp (modified) (3 diffs)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (1 diff)
-
src/ResolvExpr/CandidateFinder.hpp (modified) (3 diffs)
-
src/ResolvExpr/CurrentObject.cc (modified) (1 diff)
-
src/ResolvExpr/CurrentObject.h (modified) (1 diff)
-
src/ResolvExpr/ExplodedActual.cc (modified) (2 diffs)
-
src/ResolvExpr/ExplodedActual.h (modified) (2 diffs)
-
src/ResolvExpr/ExplodedArg.cpp (deleted)
-
src/ResolvExpr/ExplodedArg.hpp (deleted)
-
src/ResolvExpr/ResolvMode.h (modified) (2 diffs)
-
src/ResolvExpr/Resolver.cc (modified) (14 diffs)
-
src/ResolvExpr/Resolver.h (modified) (3 diffs)
-
src/ResolvExpr/SatisfyAssertions.cpp (deleted)
-
src/ResolvExpr/SatisfyAssertions.hpp (deleted)
-
src/ResolvExpr/Unify.cc (modified) (1 diff)
-
src/ResolvExpr/Unify.h (modified) (1 diff)
-
src/ResolvExpr/module.mk (modified) (2 diffs)
-
src/ResolvExpr/typeops.h (modified) (1 diff)
-
src/Tuples/Explode.h (modified) (2 diffs)
-
src/Tuples/TupleAssignment.cc (modified) (1 diff)
-
src/Tuples/Tuples.h (modified) (2 diffs)
-
tests/.expect/manipulatorsInput.txt (deleted)
-
tests/.expect/manipulatorsOutput1.txt (deleted)
-
tests/.expect/manipulatorsOutput2.x64.txt (deleted)
-
tests/.expect/manipulatorsOutput2.x86.txt (deleted)
-
tests/.in/manipulatorsInput.txt (deleted)
-
tests/manipulatorsInput.cfa (deleted)
-
tests/manipulatorsOutput1.cfa (deleted)
-
tests/manipulatorsOutput2.cfa (deleted)
-
tests/sum.cfa (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/iostream.cfa
r21300d7 raaeacf4 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // iostream.c fa--7 // iostream.c -- 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 : Wed Jun 12 15:00:31201913 // Update Count : 8 1912 // Last Modified On : Sun Jun 9 16:27:17 2019 13 // Update Count : 803 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 752 742 // manipulators 753 743 istype & ?|?( istype & is, istype & (* manip)( istype & ) ) { … … 777 767 // skip xxx 778 768 if ( ! f.s ) { 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, "" ); 769 // printf( "skip %s\n", f.scanset ); 770 fmt( is, f.scanset, "" ); // no input arguments 782 771 return is; 783 772 } // if … … 808 797 } // ?|? 809 798 810 forall( dtype istype | istream( istype ) )811 istype & ?|?( istype & is, _Istream_Char f ) {812 fmt( is, "%*c" ); // argument variable unused813 return is;814 } // ?|?815 816 799 #define InputFMTImpl( T, CODE ) \ 817 800 forall( dtype istype | istream( istype ) ) \ … … 819 802 enum { size = 16 }; \ 820 803 char fmtstr[size]; \ 821 if ( f.wd == -1 ) {\804 if ( f.wd == -1 || strcmp( CODE, "c" ) == 0 ) { /* ignore width with "c" */ \ 822 805 snprintf( fmtstr, size, "%%%s%s", f.ignore ? "*" : "", CODE ); \ 823 806 } else { \ … … 829 812 } // ?|? 830 813 814 InputFMTImpl( char, "c" ) 831 815 InputFMTImpl( signed char, "hhi" ) 832 816 InputFMTImpl( unsigned char, "hhi" ) -
libcfa/src/iostream.hfa
r21300d7 raaeacf4 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jun 12 13:35:42201913 // Update Count : 3 3112 // Last Modified On : Sat Jun 8 17:28:44 2019 13 // Update Count : 312 14 14 // 15 15 … … 155 155 struct _Ostream_Manip { 156 156 T val; // polymorphic base-type 157 unsigned intwd, pc; // width, precision157 unsigned char 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 intw, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, CODE, { .all : 0 } }; } \183 _Ostream_Manip(T) wd( unsigned intw, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, CODE, { .flags.pc : true } }; } \184 _Ostream_Manip(T) & wd( unsigned intw, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \185 _Ostream_Manip(T) & wd( unsigned intw, 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 char w, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, CODE, { .all : 0 } }; } \ 183 _Ostream_Manip(T) wd( unsigned char w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, CODE, { .flags.pc : true } }; } \ 184 _Ostream_Manip(T) & wd( unsigned char w, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \ 185 _Ostream_Manip(T) & wd( unsigned char 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 } /* distribution */\192 } \ 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 intw, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, 'f', { .all : 0 } }; } \217 _Ostream_Manip(T) wd( unsigned intw, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'f', { .flags.pc : true } }; } \218 _Ostream_Manip(T) ws( unsigned intw, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'g', { .flags.pc : true } }; } \219 _Ostream_Manip(T) & wd( unsigned intw, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \220 _Ostream_Manip(T) & wd( unsigned intw, 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 char w, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, 'f', { .all : 0 } }; } \ 217 _Ostream_Manip(T) wd( unsigned char w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'f', { .flags.pc : true } }; } \ 218 _Ostream_Manip(T) ws( unsigned char w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'g', { .flags.pc : true } }; } \ 219 _Ostream_Manip(T) & wd( unsigned char w, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \ 220 _Ostream_Manip(T) & wd( unsigned char 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 } /* distribution */\229 } \ 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 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 intw, _Ostream_Manip(char) & fmt ) { fmt.wd = w; return fmt; }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 char 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 * 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 intw, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; return fmt; }264 _Ostream_Manip(const char *) & wd( unsigned intw, 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 * 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 char w, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; return fmt; } 264 _Ostream_Manip(const char *) & wd( unsigned char 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 istype & ?|?( istype &, const char * );319 istype & ?|?( istype &, char * );318 // Cannot have char & and char * => cstr manipulator 319 // istype & ?|?( istype &, char * ); 320 320 321 321 // manipulators … … 341 341 }; // _Istream_Cstr 342 342 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 ); 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 ); 366 354 367 355 forall( otype T ) … … 373 361 374 362 #define InputFMTDecl( T ) \ 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 */ \ 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 }; } \ 381 366 forall( dtype istype | istream( istype ) ) { \ 382 367 istype & ?|?( istype & is, _Istream_Manip(T) f ); \ 383 368 } // ?|? 384 369 370 InputFMTDecl( char ) 385 371 InputFMTDecl( signed char ) 386 372 InputFMTDecl( unsigned char ) -
src/AST/Convert.cpp
r21300d7 raaeacf4 2193 2193 2194 2194 int isStringlikeConstantType(const Type *t) { 2195 const Type *referentType = nullptr;2196 2195 if ( const ArrayType * aty = dynamic_cast< const ArrayType * >( t ) ) { 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 ) ) { 2196 if ( const BasicType * bty = dynamic_cast< const BasicType * >( aty->base ) ) { 2203 2197 if ( bty->kind == BasicType::Kind::Char ) { 2204 2198 return true; … … 2211 2205 virtual void visit( ConstantExpr * old ) override final { 2212 2206 ast::ConstantExpr *rslt = nullptr; 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)) { 2207 if (isIntlikeConstantType(old->result)) { 2222 2208 rslt = new ast::ConstantExpr( 2223 2209 old->location, … … 2233 2219 old->constant.get_value(), 2234 2220 (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::String 2235 2229 ); 2236 2230 } -
src/AST/Node.hpp
r21300d7 raaeacf4 99 99 100 100 /// Mutate a node field (only clones if not equal to existing value) 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 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 ) { 104 107 if ( node->*field == val ) return node; 105 108 106 // mutate and return107 109 node_t * ret = mutate( node ); 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 ); 110 ret->*field = std::forward< field_t >( val ); 123 111 return ret; 124 112 } -
src/AST/Print.hpp
r21300d7 raaeacf4 16 16 #pragma once 17 17 18 #include <ios tream>19 #include <utility> // for forward18 #include <iosfwd> 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 /// 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 } 34 inline void printShort( std::ostream & os, const ast::Decl * node, unsigned int indent ) { 35 printShort( os, node, Indenter{ indent } ); 44 36 } 45 37 -
src/AST/porting.md
r21300d7 raaeacf4 299 299 * `openVars` => `open` 300 300 301 `ExplodedActual` => `ExplodedArg`302 * `ExplodedActual.h` => `ExplodedArg.hpp`303 304 301 [1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes 305 302 -
src/InitTweak/InitTweak.cc
r21300d7 raaeacf4 1 //2 // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo3 //4 // The contents of this file are covered under the licence agreement in the5 // file "LICENCE" distributed with Cforall.6 //7 // InitTweak.cc --8 //9 // Author : Rob Schluntz10 // Created On : Fri May 13 11:26:36 201611 // Last Modified By : Aaron B. Moss12 // Last Modified On : Mon Jun 10 13:30:00 201913 // Update Count : 514 //15 16 1 #include <algorithm> // for find, all_of 17 2 #include <cassert> // for assertf, assert, strict_dynamic_cast … … 19 4 #include <iterator> // for back_insert_iterator, back_inserter 20 5 #include <memory> // for __shared_ptr 21 #include <vector>22 6 23 7 #include "AST/Expr.hpp" … … 323 307 } 324 308 325 struct CallFinder _old{326 CallFinder _old( const std::list< std::string > & names ) : names( names ) {}309 struct CallFinder { 310 CallFinder( const std::list< std::string > & names ) : names( names ) {} 327 311 328 312 void postvisit( ApplicationExpr * appExpr ) { … … 347 331 }; 348 332 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 366 333 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) { 367 static PassVisitor<CallFinder _old> finder( std::list< std::string >{ "?{}", "^?{}" } );334 static PassVisitor<CallFinder> finder( std::list< std::string >{ "?{}", "^?{}" } ); 368 335 finder.pass.matches = &matches; 369 336 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 );376 337 } 377 338 … … 475 436 } 476 437 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 because486 // autogenerated ctor/dtor will call all member dtors, and some members may have a487 // user-defined dtor488 return func->linkage == ast::Linkage::Intrinsic ? appExpr : nullptr;489 }490 491 438 namespace { 492 439 template <typename Predicate> … … 497 444 return std::all_of( callExprs.begin(), callExprs.end(), pred); 498 445 } 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 }505 446 } 506 447 … … 511 452 assert( funcType ); 512 453 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;525 454 } 526 455 return false; -
src/InitTweak/InitTweak.h
r21300d7 raaeacf4 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // InitTweak.h --7 // RemoveInit.h -- 8 8 // 9 9 // Author : Rob Schluntz 10 10 // Created On : Fri May 13 11:26:36 2016 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Mon Jun 10 13:30:00 201913 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:30:33 2017 13 // Update Count : 4 14 14 // 15 15 … … 19 19 #include <memory> // for shared_ptr 20 20 #include <string> // for string, allocator 21 #include <vector>22 21 23 22 #include "AST/Fwd.hpp" // for AST nodes … … 64 63 /// Non-Null if expr is a call expression whose target function is intrinsic 65 64 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ); 66 const ast::ApplicationExpr * isIntrinsicCallExpr( const ast::Expr * expr);67 65 68 66 /// True if stmt is a call statement where the function called is intrinsic and takes one parameter. … … 70 68 /// Currently has assertions that make it less than fully general. 71 69 bool isIntrinsicSingleArgCallStmt( Statement * stmt ); 72 bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt );73 70 74 71 /// True if stmt is a call statement where the function called is intrinsic. … … 77 74 /// get all Ctor/Dtor call expressions from a Statement 78 75 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ); 79 std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt );80 76 81 77 /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call -
src/Makefile.in
r21300d7 raaeacf4 195 195 ResolvExpr/CurrentObject.$(OBJEXT) \ 196 196 ResolvExpr/ExplodedActual.$(OBJEXT) \ 197 ResolvExpr/ExplodedArg.$(OBJEXT) \198 197 ResolvExpr/FindOpenVars.$(OBJEXT) ResolvExpr/Occurs.$(OBJEXT) \ 199 198 ResolvExpr/PolyCost.$(OBJEXT) \ … … 204 203 ResolvExpr/Resolver.$(OBJEXT) \ 205 204 ResolvExpr/ResolveTypeof.$(OBJEXT) \ 206 ResolvExpr/SatisfyAssertions.$(OBJEXT) \207 205 ResolvExpr/SpecCost.$(OBJEXT) \ 208 206 ResolvExpr/TypeEnvironment.$(OBJEXT) \ … … 634 632 ResolvExpr/CurrentObject.cc \ 635 633 ResolvExpr/ExplodedActual.cc \ 636 ResolvExpr/ExplodedArg.cpp \637 634 ResolvExpr/FindOpenVars.cc \ 638 635 ResolvExpr/Occurs.cc \ … … 644 641 ResolvExpr/Resolver.cc \ 645 642 ResolvExpr/ResolveTypeof.cc \ 646 ResolvExpr/SatisfyAssertions.cpp \647 643 ResolvExpr/SpecCost.cc \ 648 644 ResolvExpr/TypeEnvironment.cc \ … … 897 893 ResolvExpr/ExplodedActual.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 898 894 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 899 ResolvExpr/ExplodedArg.$(OBJEXT): ResolvExpr/$(am__dirstamp) \900 ResolvExpr/$(DEPDIR)/$(am__dirstamp)901 895 ResolvExpr/FindOpenVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 902 896 ResolvExpr/$(DEPDIR)/$(am__dirstamp) … … 916 910 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 917 911 ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 918 ResolvExpr/$(DEPDIR)/$(am__dirstamp)919 ResolvExpr/SatisfyAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \920 912 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 921 913 ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ … … 1281 1273 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CurrentObject.Po@am__quote@ 1282 1274 @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@1284 1275 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/FindOpenVars.Po@am__quote@ 1285 1276 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Occurs.Po@am__quote@ … … 1291 1282 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@ 1292 1283 @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@1294 1284 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/SpecCost.Po@am__quote@ 1295 1285 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@ -
src/ResolvExpr/AdjustExprType.cc
r21300d7 raaeacf4 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // AdjustExprType _old.cc --7 // AdjustExprType.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"21 16 #include "Common/PassVisitor.h" 22 17 #include "SymTab/Indexer.h" // for Indexer … … 27 22 28 23 namespace ResolvExpr { 29 30 namespace { 31 class AdjustExprType_old final : public WithShortCircuiting { 32 public: 33 AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer ); 24 class AdjustExprType : public WithShortCircuiting { 25 public: 26 AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer ); 34 27 void premutate( VoidType * ) { visit_children = false; } 35 28 void premutate( BasicType * ) { visit_children = false; } … … 51 44 Type * postmutate( TypeInstType *aggregateUseType ); 52 45 53 private:46 private: 54 47 const TypeEnvironment & env; 55 48 const SymTab::Indexer & indexer; 56 49 }; 57 50 58 AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer ) 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 ) 59 64 : env( env ), indexer( indexer ) { 60 65 } 61 66 62 Type * AdjustExprType _old::postmutate( ArrayType * arrayType ) {67 Type * AdjustExprType::postmutate( ArrayType * arrayType ) { 63 68 PointerType *pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base }; 64 69 arrayType->base = nullptr; … … 67 72 } 68 73 69 Type * AdjustExprType _old::postmutate( FunctionType * functionType ) {74 Type * AdjustExprType::postmutate( FunctionType * functionType ) { 70 75 return new PointerType{ Type::Qualifiers(), functionType }; 71 76 } 72 77 73 Type * AdjustExprType _old::postmutate( TypeInstType * typeInst ) {78 Type * AdjustExprType::postmutate( TypeInstType * typeInst ) { 74 79 if ( const EqvClass* eqvClass = env.lookup( typeInst->get_name() ) ) { 75 80 if ( eqvClass->data.kind == TypeDecl::Ftype ) { … … 85 90 return typeInst; 86 91 } 87 } // anonymous namespace88 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-function134 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 namespace149 150 const ast::Type * adjustExprType(151 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab152 ) {153 ast::Pass<AdjustExprType_new> adjuster{ env, symtab };154 return type->accept( adjuster );155 }156 157 92 } // namespace ResolvExpr 158 93 -
src/ResolvExpr/AlternativeFinder.cc
r21300d7 raaeacf4 29 29 #include "AlternativeFinder.h" 30 30 #include "AST/Expr.hpp" 31 #include "AST/SymbolTable.hpp"32 31 #include "AST/Type.hpp" 33 32 #include "Common/SemanticError.h" // for SemanticError … … 116 115 /// Finds matching alternatives for a function, given a set of arguments 117 116 template<typename OutputIterator> 118 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs _old& args, OutputIterator out );117 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 119 118 /// Sets up parameter inference for an output alternative 120 119 template< typename OutputIterator > … … 267 266 SemanticError( expr, "No reasonable alternatives for expression " ); 268 267 } 269 if ( mode. satisfyAssns || mode.prune ) {268 if ( mode.resolveAssns || mode.prune ) { 270 269 // trim candidates just to those where the assertions resolve 271 270 // - necessary pre-requisite to pruning … … 593 592 594 593 /// Gets the list of exploded alternatives for this pack 595 const ExplodedActual& getExpl( const ExplodedArgs _old& args ) const {594 const ExplodedActual& getExpl( const ExplodedArgs& args ) const { 596 595 return args[nextArg-1][explAlt]; 597 596 } … … 617 616 /// Instantiates an argument to match a formal, returns false if no results left 618 617 bool instantiateArgument( Type* formalType, Initializer* initializer, 619 const ExplodedArgs _old& args, std::vector<ArgPack>& results, std::size_t& genStart,618 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 620 619 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 621 620 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) { … … 889 888 template<typename OutputIterator> 890 889 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 891 FunctionType *funcType, const ExplodedArgs _old&args, OutputIterator out ) {890 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 892 891 OpenVarSet funcOpenVars; 893 892 AssertionSet funcNeed, funcHave; … … 1021 1020 1022 1021 // pre-explode arguments 1023 ExplodedArgs _oldargExpansions;1022 ExplodedArgs argExpansions; 1024 1023 argExpansions.reserve( argAlternatives.size() ); 1025 1024 -
src/ResolvExpr/AlternativeFinder.h
r21300d7 raaeacf4 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 _old= std::vector< std::vector< ExplodedActual > >;39 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >; 40 40 41 41 class AlternativeFinder { -
src/ResolvExpr/Candidate.hpp
r21300d7 raaeacf4 30 30 /// A list of unresolved assertions 31 31 using AssertionList = std::vector<AssertionSet::value_type>; 32 33 /// Convenience to merge AssertionList into AssertionSet34 static inline void mergeAssertionSet( AssertionSet & dst, const AssertionList & src ) {35 for ( const auto & s : src ) { dst.emplace( s ); }36 }37 32 } 38 33 … … 47 42 ast::OpenVarSet open; ///< Open variables for environment 48 43 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() ) {}64 44 }; 65 45 … … 69 49 /// List of candidates 70 50 using CandidateList = std::vector< CandidateRef >; 71 72 /// Splice src after dst, clearing src73 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 dst80 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 candidates86 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 }98 51 99 52 void print( std::ostream & os, const Candidate & cand, Indenter indent = {} ); -
src/ResolvExpr/CandidateFinder.cpp
r21300d7 raaeacf4 16 16 #include "CandidateFinder.hpp" 17 17 18 #include <deque>19 #include <iterator> // for back_inserter20 #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 adjustExprType32 #include "Unify.h"33 18 #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 handleTupleAssignment41 42 #define PRINT( text ) if ( resolvep ) { text }43 19 44 20 namespace ResolvExpr { 45 21 46 namespace {47 48 /// First index is which argument, second is which alternative, third is which exploded element49 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;50 51 /// Returns a list of alternatives with the minimum cost in the given list52 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 candidate68 Cost computeApplicationConversionCost(69 const CandidateRef & cand, const ast::SymbolTable & symtab70 ) {71 #warning unimplemented72 (void)cand; (void)symtab;73 assert(false);74 return Cost::infinity;75 }76 77 /// Actually visits expressions to find their candidate interpretations78 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 list92 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 out102 void makeFunctionCandidates(103 const CandidateRef & func, const ast::FunctionType * funcType,104 const ExplodedArgs_new & args, CandidateList & out105 ) {106 #warning unimplemented107 (void)func; (void)funcType; (void)args; (void)out;108 assert(false);109 }110 111 /// Adds implicit struct-conversions to the alternative list112 void addAnonConversions( const CandidateRef & cand ) {113 #warning unimplemented114 (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 candidates122 if ( funcFinder.candidates.empty() ) return;123 124 std::vector< CandidateFinder > argCandidates =125 selfFinder.findSubExprs( untypedExpr->args );126 127 // take care of possible tuple assignments128 // if not tuple assignment, handled as normal function call129 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );130 131 // find function operators132 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" };133 CandidateFinder opFinder{ symtab, tenv };134 // okay if there aren't any function operations135 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 arguments142 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 matches150 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 function160 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 list186 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-function196 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-error210 // candidates211 if ( found.empty() && ! errors.isEmpty() ) { throw errors; }212 213 // Compute conversion costs214 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 twice241 CandidateList winners = findMinCost( found );242 promoteCvtCost( winners );243 244 // function may return a struct/union value, in which case we need to add candidates245 // for implicit conversions to each of the anonymous members, which must happen after246 // `findMinCost`, since anon conversions are never the cheapest247 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 it254 // 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 char261 // * (x: const char *) is unified with unsigned char *, which fails262 // xxx -- fix this better263 targetType = nullptr;264 postvisit( untypedExpr );265 }266 }267 268 /// true if expression is an lvalue269 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 unimplemented288 (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 type296 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 unimplemented305 (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 unimplemented315 (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 since321 // creation322 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 unimplemented332 (void)sizeofExpr;333 assert(false);334 }335 336 void postvisit( const ast::AlignofExpr * alignofExpr ) {337 #warning unimplemented338 (void)alignofExpr;339 assert(false);340 }341 342 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {343 #warning unimplemented344 (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 condition386 CandidateFinder finder1{ symtab, tenv };387 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );388 if ( finder1.candidates.empty() ) return;389 390 // candidates for true result391 CandidateFinder finder2{ symtab, tenv };392 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );393 if ( finder2.candidates.empty() ) return;394 395 // candidates for false result396 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 new416 // candidates417 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 unimplemented424 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 unify457 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 unimplemented487 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 unimplemented542 (void)stmtExpr;543 assert(false);544 }545 546 void postvisit( const ast::UntypedInitExpr * initExpr ) {547 #warning unimplemented548 (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 given566 /// 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 type577 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 option598 // that is at least as good599 if ( findDeletedExpr( candidate->expr ) ) {600 // do nothing601 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 candidates621 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 namespace638 639 22 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) { 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; 23 #warning unimplemented 24 (void)expr; (void)mode; 25 assert(false); 737 26 } 738 27 -
src/ResolvExpr/CandidateFinder.hpp
r21300d7 raaeacf4 19 19 #include "ResolvMode.h" 20 20 #include "AST/Fwd.hpp" 21 #include "AST/Node.hpp"22 21 #include "AST/SymbolTable.hpp" 23 22 #include "AST/TypeEnvironment.hpp" … … 30 29 const ast::SymbolTable & symtab; ///< Symbol table to lookup candidates 31 30 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 32 ast::ptr< ast::Type >targetType = nullptr; ///< Target type for resolution31 const ast::Type * targetType = nullptr; ///< Target type for resolution 33 32 34 33 CandidateFinder( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) … … 37 36 /// Fill candidates with feasible resolutions for `expr` 38 37 void find( const ast::Expr * expr, ResolvMode mode = {} ); 39 40 /// Runs new candidate finder on each element in xs, returning the list of finders41 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(); }52 38 }; 53 39 -
src/ResolvExpr/CurrentObject.cc
r21300d7 raaeacf4 946 946 } 947 947 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 ) { 948 void CurrentObject::setNext( const ast::Designation * designation ) { 1022 949 PRINT( std::cerr << "____setNext" << designation << std::endl; ) 1023 950 assertf( ! objStack.empty(), "obj stack empty in setNext" ); -
src/ResolvExpr/CurrentObject.h
r21300d7 raaeacf4 111 111 CurrentObject( const CodeLocation & loc, const Type * type ); 112 112 113 /// resolves unresolved designation114 const Designation * findNext( const Designation * designation );115 113 /// sets current position using the resolved designation 116 114 void setNext( const ast::Designation * designation ); -
src/ResolvExpr/ExplodedActual.cc
r21300d7 raaeacf4 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ExplodedActual.cc--7 // Alternative.h -- 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
r21300d7 raaeacf4 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ExplodedActual.h --7 // Alternative.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
r21300d7 raaeacf4 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 satisfyAssns; ///< Satisfyassertions? [false]24 const bool resolveAssns; ///< Resolve assertions? [false] 25 25 26 26 private: 27 constexpr ResolvMode(bool a, bool p, bool ff, bool sa)28 : adjust(a), prune(p), failFast(ff), satisfyAssns(sa) {}27 constexpr ResolvMode(bool a, bool p, bool ff, bool ra) 28 : adjust(a), prune(p), failFast(ff), resolveAssns(ra) {} 29 29 30 30 public: 31 31 /// Default settings 32 constexpr ResolvMode() : adjust(false), prune(true), failFast(true), satisfyAssns(false) {}32 constexpr ResolvMode() : adjust(false), prune(true), failFast(true), resolveAssns(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 satisfyAssns turned on; for top-level calls45 /// The same mode, but with resolveAssns turned on; for top-level calls 46 46 ResolvMode atTopLevel() const { return { adjust, prune, failFast, true }; } 47 47 }; -
src/ResolvExpr/Resolver.cc
r21300d7 raaeacf4 35 35 #include "AST/Print.hpp" 36 36 #include "AST/SymbolTable.hpp" 37 #include "AST/Type.hpp"38 37 #include "Common/PassVisitor.h" // for PassVisitor 39 38 #include "Common/SemanticError.h" // for SemanticError … … 957 956 } 958 957 }; 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 { 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 969 966 /// always-accept candidate filter 970 967 bool anyCandidate( const Candidate & ) { return true; } … … 1026 1023 1027 1024 // promote candidate.cvtCost to .cost 1028 promoteCvtCost( winners ); 1025 for ( CandidateRef & cand : winners ) { 1026 cand->cost = cand->cvtCost; 1027 } 1029 1028 1030 1029 // produce ambiguous errors, if applicable … … 1100 1099 StripCasts_new::strip( expr ); 1101 1100 } 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 { 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 1124 1122 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1125 1123 /// context. … … 1148 1146 } 1149 1147 1150 /// Resolve `untyped` to the single expression whose candidate is the best match1151 ast::ptr< ast::Expr > findSingleExpression(1152 const ast::Expr * untyped, const ast::SymbolTable & symtab1153 ) {1154 return findKindExpression( untyped, symtab );1155 }1156 1157 1148 /// Resolve `untyped` to the single expression whose candidate is the best match for the 1158 1149 /// given type. … … 1161 1152 ) { 1162 1153 assert( untyped && type ); 1163 ast::ptr< ast::Expr >castExpr = new ast::CastExpr{ untyped->location, untyped, type };1164 ast::ptr< ast::Expr > newExpr = find SingleExpression( castExpr, symtab );1154 const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type }; 1155 ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab ); 1165 1156 removeExtraneousCast( newExpr, symtab ); 1166 1157 return newExpr; … … 1198 1189 return false; 1199 1190 } 1200 1201 /// Advance a type itertor to the next mutex parameter1202 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 }1207 1191 } 1208 1192 … … 1229 1213 void previsit( const ast::PointerType * ); 1230 1214 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 * );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 void previsit( const ast::WaitForStmt * ); 1228 1229 const ast::SingleInit * previsit( const ast::SingleInit * ); 1230 const ast::ListInit * previsit( const ast::ListInit * ); 1231 void previsit( const ast::ConstructorInit * ); 1248 1232 }; 1249 1233 … … 1397 1381 "expression." ); 1398 1382 1399 ast::ptr< ast::Expr >untyped =1383 const ast::Expr * untyped = 1400 1384 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1401 ast::ptr< ast::Expr > newExpr = find SingleExpression( untyped, symtab );1385 ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab ); 1402 1386 1403 1387 // case condition cannot have a cast in C, so it must be removed here, regardless of … … 1417 1401 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 1418 1402 // computed goto argument is void* 1419 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };1420 1403 branchStmt = ast::mutate_field( 1421 1404 branchStmt, &ast::BranchStmt::computedTarget, 1422 findSingleExpression( branchStmt->computedTarget, target, symtab ) ); 1405 findSingleExpression( 1406 branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 1407 symtab ) ); 1423 1408 } 1424 1409 return branchStmt; … … 1460 1445 } 1461 1446 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; 1447 void Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1448 #warning unimplemented; Resolver port in progress 1449 (void)stmt; 1450 assert(false); 1712 1451 } 1713 1452 … … 1718 1457 // resolve initialization using the possibilities as determined by the `currentObject` 1719 1458 // cursor. 1720 ast:: ptr< ast::Expr >untyped = new ast::UntypedInitExpr{1459 ast::Expr * untyped = new ast::UntypedInitExpr{ 1721 1460 singleInit->location, singleInit->value, currentObject.getOptions() }; 1722 ast::ptr<ast::Expr> newExpr = find SingleExpression( untyped, symtab );1461 ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab ); 1723 1462 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 1724 1463 … … 1771 1510 // iterate designations and initializers in pairs, moving the cursor to the current 1772 1511 // designated object and resolving the initializer against that object 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(); 1512 #warning unimplemented; Resolver port in progress 1513 assert(false); 1514 } 1783 1515 1784 1516 visit_children = false; … … 1786 1518 } 1787 1519 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; 1520 void Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) { 1521 #warning unimplemented; Resolver port in progress 1522 (void)ctorInit; 1523 assert(false); 1807 1524 } 1808 1525 -
src/ResolvExpr/Resolver.h
r21300d7 raaeacf4 17 17 18 18 #include <list> // for list 19 20 #include "AST/Node.hpp" // for ptr 19 #include <AST/Node.hpp> // for ptr 21 20 22 21 class ConstructorInit; … … 30 29 namespace ast { 31 30 class Decl; 32 class DeletedExpr;33 class SymbolTable;34 class TypeEnvironment;35 31 } // namespace ast 36 32 … … 52 48 /// Checks types and binds syntactic constructs to typed representations 53 49 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ); 54 /// Searches expr and returns the first DeletedExpr found, otherwise nullptr55 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 );60 50 } // namespace ResolvExpr 61 51 -
src/ResolvExpr/Unify.cc
r21300d7 raaeacf4 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 & symtab1146 ) {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,1154 1145 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common 1155 1146 ) { -
src/ResolvExpr/Unify.h
r21300d7 raaeacf4 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,79 74 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common ); 80 75 -
src/ResolvExpr/module.mk
r21300d7 raaeacf4 26 26 ResolvExpr/CurrentObject.cc \ 27 27 ResolvExpr/ExplodedActual.cc \ 28 ResolvExpr/ExplodedArg.cpp \29 28 ResolvExpr/FindOpenVars.cc \ 30 29 ResolvExpr/Occurs.cc \ … … 36 35 ResolvExpr/Resolver.cc \ 37 36 ResolvExpr/ResolveTypeof.cc \ 38 ResolvExpr/SatisfyAssertions.cpp \39 37 ResolvExpr/SpecCost.cc \ 40 38 ResolvExpr/TypeEnvironment.cc \ -
src/ResolvExpr/typeops.h
r21300d7 raaeacf4 71 71 } // while 72 72 } 73 74 /// Replaces array types with equivalent pointer, and function types with a pointer-to-function75 const ast::Type * adjustExprType(76 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );77 73 78 74 // in CastCost.cc -
src/Tuples/Explode.h
r21300d7 raaeacf4 19 19 #include <utility> // for forward 20 20 21 #include "AST/Expr.hpp"22 21 #include "ResolvExpr/Alternative.h" // for Alternative, AltList 23 #include "ResolvExpr/Candidate.hpp" // for Candidate, CandidateList24 22 #include "ResolvExpr/ExplodedActual.h" // for ExplodedActual 25 #include "ResolvExpr/ExplodedArg.hpp" // for ExplodedArg26 23 #include "SynTree/Expression.h" // for Expression, UniqueExpr, AddressExpr 27 24 #include "SynTree/Type.h" // for TupleType, Type 28 25 #include "Tuples.h" // for maybeImpure 29 30 namespace ast {31 class SymbolTable;32 }33 26 34 27 namespace SymTab { … … 137 130 explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign ); 138 131 } 139 140 /// helper function used by explode141 template< typename Output >142 void explodeUnique(143 const ast::Expr * expr, const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab,144 Output && out, bool isTupleAssign145 ) {146 #warning unimplemented147 (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 type152 template< typename Output >153 void explode(154 const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out,155 bool isTupleAssign = false156 ) {157 explodeUnique( arg.expr, arg, symtab, std::forward< Output >( out ), isTupleAssign );158 }159 160 132 } // namespace Tuples 161 133 -
src/Tuples/TupleAssignment.cc
r21300d7 raaeacf4 377 377 } 378 378 } 379 380 void handleTupleAssignment(381 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,382 std::vector< ResolvExpr::CandidateFinder > & args383 ) {384 #warning unimplmented385 (void)finder; (void)assign; (void)args;386 assert(false);387 }388 379 } // namespace Tuples 389 380 -
src/Tuples/Tuples.h
r21300d7 raaeacf4 26 26 27 27 #include "ResolvExpr/AlternativeFinder.h" 28 #include "ResolvExpr/CandidateFinder.hpp"29 28 30 29 namespace Tuples { … … 32 31 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, 33 32 std::vector< ResolvExpr::AlternativeFinder >& args ); 34 void handleTupleAssignment(35 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,36 std::vector< ResolvExpr::CandidateFinder > & args );37 33 38 34 // TupleExpansion.cc -
tests/sum.cfa
r21300d7 raaeacf4 11 11 // Created On : Wed May 27 17:56:53 2015 12 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Thu Jun 6 16:18:22 201914 // Update Count : 33 313 // Last Modified On : Sun May 19 11:21:02 2019 14 // Update Count : 330 15 15 // 16 16 … … 111 111 }; 112 112 GS(int) gs; 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 113 gs.x = anew( size ); // create array storage for field 115 114 s = 0; v = low; 116 115 for ( int i = 0; i < size; i += 1, v += 1 ) {
Note:
See TracChangeset
for help on using the changeset viewer.