Changes in / [21300d7:aaeacf4]


Ignore:
Files:
12 deleted
30 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/iostream.cfa

    r21300d7 raaeacf4  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // iostream.cfa --
     7// iostream.c --
    88//
    99// Author           : Peter A. Buhr
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 12 15:00:31 2019
    13 // Update Count     : 819
     12// Last Modified On : Sun Jun  9 16:27:17 2019
     13// Update Count     : 803
    1414//
    1515
     
    740740        } // ?|?
    741741
    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 
    752742        // manipulators
    753743        istype & ?|?( istype & is, istype & (* manip)( istype & ) ) {
     
    777767        // skip xxx
    778768        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
    782771                return is;
    783772        } // if
     
    808797} // ?|?
    809798
    810 forall( dtype istype | istream( istype ) )
    811 istype & ?|?( istype & is, _Istream_Char f ) {
    812         fmt( is, "%*c" );                                                                       // argument variable unused
    813         return is;
    814 } // ?|?
    815 
    816799#define InputFMTImpl( T, CODE ) \
    817800forall( dtype istype | istream( istype ) ) \
     
    819802        enum { size = 16 }; \
    820803        char fmtstr[size]; \
    821         if ( f.wd == -1 ) { \
     804        if ( f.wd == -1 || strcmp( CODE, "c" ) == 0 ) { /* ignore width with "c" */     \
    822805                snprintf( fmtstr, size, "%%%s%s", f.ignore ? "*" : "", CODE ); \
    823806        } else { \
     
    829812} // ?|?
    830813
     814InputFMTImpl( char, "c" )
    831815InputFMTImpl( signed char, "hhi" )
    832816InputFMTImpl( unsigned char, "hhi" )
  • libcfa/src/iostream.hfa

    r21300d7 raaeacf4  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 12 13:35:42 2019
    13 // Update Count     : 331
     12// Last Modified On : Sat Jun  8 17:28:44 2019
     13// Update Count     : 312
    1414//
    1515
     
    155155struct _Ostream_Manip {
    156156        T val;                                                                                          // polymorphic base-type
    157         unsigned int wd, pc;                                                            // width, precision
     157        unsigned char wd, pc;                                                           // width, precision
    158158        char base;                                                                                      // numeric base / floating-point style
    159159        union {
     
    180180        _Ostream_Manip(T) oct( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'o', { .all : 0 } }; } \
    181181        _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'x', { .all : 0 } }; } \
    182         _Ostream_Manip(T) wd( unsigned int w, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, CODE, { .all : 0 } }; } \
    183         _Ostream_Manip(T) wd( unsigned int w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, CODE, { .flags.pc : true } }; } \
    184         _Ostream_Manip(T) & wd( unsigned int w, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \
    185         _Ostream_Manip(T) & wd( unsigned int w, unsigned char pc, _Ostream_Manip(T) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
     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; } \
    186186        _Ostream_Manip(T) & left( _Ostream_Manip(T) & fmt ) { fmt.flags.left = true; return fmt; } \
    187187        _Ostream_Manip(T) & upcase( _Ostream_Manip(T) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; } \
     
    190190        _Ostream_Manip(T) sign( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, CODE, { .flags.sign : true } }; } \
    191191        _Ostream_Manip(T) & sign( _Ostream_Manip(T) & fmt ) { fmt.flags.sign = true; return fmt; } \
    192 } /* distribution */ \
     192} \
    193193forall( dtype ostype | ostream( ostype ) ) { \
    194194        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \
     
    214214        _Ostream_Manip(T) hex( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'a', { .all : 0 } }; } \
    215215        _Ostream_Manip(T) sci( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'e', { .all : 0 } }; } \
    216         _Ostream_Manip(T) wd( unsigned int w, T val ) { return (_Ostream_Manip(T))@{ val, w, 0, 'f', { .all : 0 } }; } \
    217         _Ostream_Manip(T) wd( unsigned int w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'f', { .flags.pc : true } }; } \
    218         _Ostream_Manip(T) ws( unsigned int w, unsigned char pc, T val ) { return (_Ostream_Manip(T))@{ val, w, pc, 'g', { .flags.pc : true } }; } \
    219         _Ostream_Manip(T) & wd( unsigned int w, _Ostream_Manip(T) & fmt ) { fmt.wd = w; return fmt; } \
    220         _Ostream_Manip(T) & wd( unsigned int w, unsigned char pc, _Ostream_Manip(T) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; } \
     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; } \
    221221        _Ostream_Manip(T) & left( _Ostream_Manip(T) & fmt ) { fmt.flags.left = true; return fmt; } \
    222222        _Ostream_Manip(T) upcase( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'G', { .all : 0 } }; } \
     
    227227        _Ostream_Manip(T) nodp( T val ) { return (_Ostream_Manip(T))@{ val, 1, 0, 'g', { .flags.nobsdp : true } }; } \
    228228        _Ostream_Manip(T) & nodp( _Ostream_Manip(T) & fmt ) { fmt.flags.nobsdp = true; return fmt; } \
    229 } /* distribution */ \
     229} \
    230230forall( dtype ostype | ostream( ostype ) ) { \
    231231        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ); \
     
    239239
    240240static 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 int w, _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; }
    246246        _Ostream_Manip(char) & left( _Ostream_Manip(char) & fmt ) { fmt.flags.left = true; return fmt; }
    247247        _Ostream_Manip(char) & upcase( _Ostream_Manip(char) & fmt ) { if ( fmt.base == 'x' || fmt.base == 'b' ) fmt.base -= 32; /* upper case */ return fmt; }
     
    256256
    257257static 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 int w, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; return fmt; }
    264         _Ostream_Manip(const char *) & wd( unsigned int w, unsigned char pc, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; }
     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; }
    265265        _Ostream_Manip(const char *) & left( _Ostream_Manip(const char *) & fmt ) { fmt.flags.left = true; return fmt; }
    266266        _Ostream_Manip(const char *) & nobase( _Ostream_Manip(const char *) & fmt ) { fmt.flags.nobsdp = true; return fmt; }
     
    316316        istype & ?|?( istype &, long double _Complex & );
    317317
    318         istype & ?|?( istype &, const char * );
    319         istype & ?|?( istype &, char * );
     318        // Cannot have char & and char * => cstr manipulator
     319        // istype & ?|?( istype &, char * );
    320320
    321321        // manipulators
     
    341341}; // _Istream_Cstr
    342342
    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 );
     343static inline _Istream_Cstr skip( const char * scanset ) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; }
     344static inline _Istream_Cstr incl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; }
     345static inline _Istream_Cstr incl( const char * scanset, _Istream_Cstr & fmt ) { fmt.flags.inex = false; return fmt; }
     346static inline _Istream_Cstr excl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; }
     347static inline _Istream_Cstr excl( const char * scanset, _Istream_Cstr & fmt ) { fmt.flags.inex = true; return fmt; }
     348static inline _Istream_Cstr cstr( char * s ) { return (_Istream_Cstr){ s, 0p, -1, { .all : 0 } }; }
     349static inline _Istream_Cstr ignore( const char * s ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; }
     350static inline _Istream_Cstr ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; }
     351static inline _Istream_Cstr wd( unsigned int w, char * s ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; }
     352static inline _Istream_Cstr wd( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; }
     353forall( dtype istype | istream( istype ) ) istype & ?|?( istype &, _Istream_Cstr );
    366354
    367355forall( otype T )
     
    373361
    374362#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 */ \
     363static inline _Istream_Manip(T) ignore( const T & val ) { return (_Istream_Manip(T))@{ (T &)val, -1, true }; } \
     364static inline _Istream_Manip(T) ignore( _Istream_Manip(T) & fmt ) { fmt.ignore = true; return fmt; } \
     365static inline _Istream_Manip(T) wd( unsigned int w, T & val ) { return (_Istream_Manip(T))@{ val, w, false }; } \
    381366forall( dtype istype | istream( istype ) ) { \
    382367        istype & ?|?( istype & is, _Istream_Manip(T) f ); \
    383368} // ?|?
    384369
     370InputFMTDecl( char )
    385371InputFMTDecl( signed char )
    386372InputFMTDecl( unsigned char )
  • src/AST/Convert.cpp

    r21300d7 raaeacf4  
    21932193
    21942194        int isStringlikeConstantType(const Type *t) {
    2195                 const Type *referentType = nullptr;
    21962195                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 ) ) {
    22032197                           if ( bty->kind == BasicType::Kind::Char ) {
    22042198                                   return true;
     
    22112205        virtual void visit( ConstantExpr * old ) override final {
    22122206                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)) {
    22222208                        rslt = new ast::ConstantExpr(
    22232209                                old->location,
     
    22332219                                old->constant.get_value(),
    22342220                                (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
    22352229                        );
    22362230                }
  • src/AST/Node.hpp

    r21300d7 raaeacf4  
    9999
    100100/// 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
     101template<typename node_t, typename field_t>
     102const 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) {
    104107        if ( node->*field == val ) return node;
    105108       
    106         // mutate and return
    107109        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 );
    123111        return ret;
    124112}
  • src/AST/Print.hpp

    r21300d7 raaeacf4  
    1616#pragma once
    1717
    18 #include <iostream>
    19 #include <utility>   // for forward
     18#include <iosfwd>
     19#include <utility> // for forward
    2020
    2121#include "AST/Node.hpp"
     
    3232void printShort( std::ostream & os, const ast::Decl * node, Indenter indent = {} );
    3333
    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     }
     34inline void printShort( std::ostream & os, const ast::Decl * node, unsigned int indent ) {
     35    printShort( os, node, Indenter{ indent } );
    4436}
    4537
  • src/AST/porting.md

    r21300d7 raaeacf4  
    299299* `openVars` => `open`
    300300
    301 `ExplodedActual` => `ExplodedArg`
    302 * `ExplodedActual.h` => `ExplodedArg.hpp`
    303 
    304301[1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes
    305302
  • src/InitTweak/InitTweak.cc

    r21300d7 raaeacf4  
    1 //
    2 // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
    3 //
    4 // The contents of this file are covered under the licence agreement in the
    5 // file "LICENCE" distributed with Cforall.
    6 //
    7 // InitTweak.cc --
    8 //
    9 // Author           : Rob Schluntz
    10 // Created On       : Fri May 13 11:26:36 2016
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 10 13:30:00 2019
    13 // Update Count     : 5
    14 //
    15 
    161#include <algorithm>               // for find, all_of
    172#include <cassert>                 // for assertf, assert, strict_dynamic_cast
     
    194#include <iterator>                // for back_insert_iterator, back_inserter
    205#include <memory>                  // for __shared_ptr
    21 #include <vector>
    226
    237#include "AST/Expr.hpp"
     
    323307        }
    324308
    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 ) {}
    327311
    328312                void postvisit( ApplicationExpr * appExpr ) {
     
    347331        };
    348332
    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 
    366333        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 >{ "?{}", "^?{}" } );
    368335                finder.pass.matches = &matches;
    369336                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 );
    376337        }
    377338
     
    475436        }
    476437
    477         const ast::ApplicationExpr * isIntrinsicCallExpr( const ast::Expr * expr ) {
    478                 auto appExpr = dynamic_cast< const ast::ApplicationExpr * >( expr );
    479                 if ( ! appExpr ) return nullptr;
    480 
    481                 const ast::DeclWithType * func = getCalledFunction( appExpr->func );
    482                 assertf( func,
    483                         "getCalledFunction returned nullptr: %s", toString( appExpr->func ).c_str() );
    484                
    485                 // check for Intrinsic only -- don't want to remove all overridable ctor/dtor because
    486                 // autogenerated ctor/dtor will call all member dtors, and some members may have a
    487                 // user-defined dtor
    488                 return func->linkage == ast::Linkage::Intrinsic ? appExpr : nullptr;
    489         }
    490 
    491438        namespace {
    492439                template <typename Predicate>
     
    497444                        return std::all_of( callExprs.begin(), callExprs.end(), pred);
    498445                }
    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                 }
    505446        }
    506447
     
    511452                                assert( funcType );
    512453                                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;
    525454                        }
    526455                        return false;
  • src/InitTweak/InitTweak.h

    r21300d7 raaeacf4  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // InitTweak.h --
     7// RemoveInit.h --
    88//
    99// Author           : Rob Schluntz
    1010// Created On       : Fri May 13 11:26:36 2016
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 10 13:30:00 2019
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:30:33 2017
     13// Update Count     : 4
    1414//
    1515
     
    1919#include <memory>             // for shared_ptr
    2020#include <string>             // for string, allocator
    21 #include <vector>
    2221
    2322#include "AST/Fwd.hpp"        // for AST nodes
     
    6463        /// Non-Null if expr is a call expression whose target function is intrinsic
    6564        ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
    66         const ast::ApplicationExpr * isIntrinsicCallExpr( const ast::Expr * expr);
    6765
    6866        /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
     
    7068        /// Currently has assertions that make it less than fully general.
    7169        bool isIntrinsicSingleArgCallStmt( Statement * stmt );
    72         bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt );
    7370
    7471        /// True if stmt is a call statement where the function called is intrinsic.
     
    7774        /// get all Ctor/Dtor call expressions from a Statement
    7875        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
    79         std::vector< ast::ptr< ast::Expr > > collectCtorDtorCalls( const ast::Stmt * stmt );
    8076
    8177        /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
  • src/Makefile.in

    r21300d7 raaeacf4  
    195195        ResolvExpr/CurrentObject.$(OBJEXT) \
    196196        ResolvExpr/ExplodedActual.$(OBJEXT) \
    197         ResolvExpr/ExplodedArg.$(OBJEXT) \
    198197        ResolvExpr/FindOpenVars.$(OBJEXT) ResolvExpr/Occurs.$(OBJEXT) \
    199198        ResolvExpr/PolyCost.$(OBJEXT) \
     
    204203        ResolvExpr/Resolver.$(OBJEXT) \
    205204        ResolvExpr/ResolveTypeof.$(OBJEXT) \
    206         ResolvExpr/SatisfyAssertions.$(OBJEXT) \
    207205        ResolvExpr/SpecCost.$(OBJEXT) \
    208206        ResolvExpr/TypeEnvironment.$(OBJEXT) \
     
    634632      ResolvExpr/CurrentObject.cc \
    635633      ResolvExpr/ExplodedActual.cc \
    636       ResolvExpr/ExplodedArg.cpp \
    637634      ResolvExpr/FindOpenVars.cc \
    638635      ResolvExpr/Occurs.cc \
     
    644641      ResolvExpr/Resolver.cc \
    645642      ResolvExpr/ResolveTypeof.cc \
    646       ResolvExpr/SatisfyAssertions.cpp \
    647643      ResolvExpr/SpecCost.cc \
    648644      ResolvExpr/TypeEnvironment.cc \
     
    897893ResolvExpr/ExplodedActual.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    898894        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    899 ResolvExpr/ExplodedArg.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    900         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    901895ResolvExpr/FindOpenVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    902896        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     
    916910        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    917911ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    918         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    919 ResolvExpr/SatisfyAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    920912        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    921913ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     
    12811273@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/CurrentObject.Po@am__quote@
    12821274@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@
    12841275@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/FindOpenVars.Po@am__quote@
    12851276@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Occurs.Po@am__quote@
     
    12911282@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@
    12921283@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@
    12941284@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/SpecCost.Po@am__quote@
    12951285@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@
  • src/ResolvExpr/AdjustExprType.cc

    r21300d7 raaeacf4  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // AdjustExprType_old.cc --
     7// AdjustExprType.cc --
    88//
    99// Author           : Richard C. Bilson
     
    1414//
    1515
    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"
    2116#include "Common/PassVisitor.h"
    2217#include "SymTab/Indexer.h"       // for Indexer
     
    2722
    2823namespace 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 );
    3427                void premutate( VoidType * ) { visit_children = false; }
    3528                void premutate( BasicType * ) { visit_children = false; }
     
    5144                Type * postmutate( TypeInstType *aggregateUseType );
    5245
    53                 private:
     46          private:
    5447                const TypeEnvironment & env;
    5548                const SymTab::Indexer & indexer;
    5649        };
    5750
    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 )
    5964                : env( env ), indexer( indexer ) {
    6065        }
    6166
    62         Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) {
     67        Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
    6368                PointerType *pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
    6469                arrayType->base = nullptr;
     
    6772        }
    6873
    69         Type * AdjustExprType_old::postmutate( FunctionType * functionType ) {
     74        Type * AdjustExprType::postmutate( FunctionType * functionType ) {
    7075                return new PointerType{ Type::Qualifiers(), functionType };
    7176        }
    7277
    73         Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) {
     78        Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
    7479                if ( const EqvClass* eqvClass = env.lookup( typeInst->get_name() ) ) {
    7580                        if ( eqvClass->data.kind == TypeDecl::Ftype ) {
     
    8590                return typeInst;
    8691        }
    87 } // anonymous namespace
    88 
    89 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    90         PassVisitor<AdjustExprType_old> adjuster( env, indexer );
    91         Type *newType = type->acceptMutator( adjuster );
    92         type = newType;
    93 }
    94 
    95 void adjustExprType( Type *& type ) {
    96         TypeEnvironment env;
    97         SymTab::Indexer indexer;
    98         adjustExprType( type, env, indexer );
    99 }
    100 
    101 namespace {
    102         struct AdjustExprType_new final : public ast::WithShortCircuiting {
    103                 const ast::TypeEnvironment & tenv;
    104                 const ast::SymbolTable & symtab;
    105 
    106                 AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
    107                 : tenv( e ), symtab( syms ) {}
    108 
    109                 void premutate( const ast::VoidType * ) { visit_children = false; }
    110                 void premutate( const ast::BasicType * ) { visit_children = false; }
    111                 void premutate( const ast::PointerType * ) { visit_children = false; }
    112                 void premutate( const ast::ArrayType * ) { visit_children = false; }
    113                 void premutate( const ast::FunctionType * ) { visit_children = false; }
    114                 void premutate( const ast::StructInstType * ) { visit_children = false; }
    115                 void premutate( const ast::UnionInstType * ) { visit_children = false; }
    116                 void premutate( const ast::EnumInstType * ) { visit_children = false; }
    117                 void premutate( const ast::TraitInstType * ) { visit_children = false; }
    118                 void premutate( const ast::TypeInstType * ) { visit_children = false; }
    119                 void premutate( const ast::TupleType * ) { visit_children = false; }
    120                 void premutate( const ast::VarArgsType * ) { visit_children = false; }
    121                 void premutate( const ast::ZeroType * ) { visit_children = false; }
    122                 void premutate( const ast::OneType * ) { visit_children = false; }
    123 
    124                 const ast::Type * postmutate( const ast::ArrayType * at ) {
    125                         return new ast::PointerType{ at->base, at->qualifiers };
    126                 }
    127 
    128                 const ast::Type * postmutate( const ast::FunctionType * ft ) {
    129                         return new ast::PointerType{ ft };
    130                 }
    131 
    132                 const ast::Type * postmutate( const ast::TypeInstType * inst ) {
    133                         // replace known function-type-variables with pointer-to-function
    134                         if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
    135                                 if ( eqvClass->data.kind == ast::TypeVar::Ftype ) {
    136                                         return new ast::PointerType{ inst };
    137                                 }
    138                         } else if ( const ast::NamedTypeDecl * ntDecl = symtab.lookupType( inst->name ) ) {
    139                                 if ( auto tyDecl = dynamic_cast< const ast::TypeDecl * >( ntDecl ) ) {
    140                                         if ( tyDecl->kind == ast::TypeVar::Ftype ) {
    141                                                 return new ast::PointerType{ inst };
    142                                         }
    143                                 }
    144                         }
    145                         return inst;
    146                 }
    147         };
    148 } // anonymous namespace
    149 
    150 const ast::Type * adjustExprType(
    151         const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
    152 ) {
    153         ast::Pass<AdjustExprType_new> adjuster{ env, symtab };
    154         return type->accept( adjuster );
    155 }
    156 
    15792} // namespace ResolvExpr
    15893
  • src/ResolvExpr/AlternativeFinder.cc

    r21300d7 raaeacf4  
    2929#include "AlternativeFinder.h"
    3030#include "AST/Expr.hpp"
    31 #include "AST/SymbolTable.hpp"
    3231#include "AST/Type.hpp"
    3332#include "Common/SemanticError.h"  // for SemanticError
     
    116115                /// Finds matching alternatives for a function, given a set of arguments
    117116                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 );
    119118                /// Sets up parameter inference for an output alternative
    120119                template< typename OutputIterator >
     
    267266                        SemanticError( expr, "No reasonable alternatives for expression " );
    268267                }
    269                 if ( mode.satisfyAssns || mode.prune ) {
     268                if ( mode.resolveAssns || mode.prune ) {
    270269                        // trim candidates just to those where the assertions resolve
    271270                        // - necessary pre-requisite to pruning
     
    593592
    594593                /// 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 {
    596595                        return args[nextArg-1][explAlt];
    597596                }
     
    617616        /// Instantiates an argument to match a formal, returns false if no results left
    618617        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,
    620619                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    621620                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     
    889888        template<typename OutputIterator>
    890889        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    891                         FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) {
     890                        FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
    892891                OpenVarSet funcOpenVars;
    893892                AssertionSet funcNeed, funcHave;
     
    10211020
    10221021                // pre-explode arguments
    1023                 ExplodedArgs_old argExpansions;
     1022                ExplodedArgs argExpansions;
    10241023                argExpansions.reserve( argAlternatives.size() );
    10251024
  • src/ResolvExpr/AlternativeFinder.h

    r21300d7 raaeacf4  
    3737        /// First index is which argument, second index is which alternative for that argument,
    3838        /// 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 > >;
    4040
    4141        class AlternativeFinder {
  • src/ResolvExpr/Candidate.hpp

    r21300d7 raaeacf4  
    3030        /// A list of unresolved assertions
    3131        using AssertionList = std::vector<AssertionSet::value_type>;
    32 
    33         /// Convenience to merge AssertionList into AssertionSet
    34         static inline void mergeAssertionSet( AssertionSet & dst, const AssertionList & src ) {
    35                 for ( const auto & s : src ) { dst.emplace( s ); }
    36         }
    3732}
    3833
     
    4742        ast::OpenVarSet open;      ///< Open variables for environment
    4843        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() ) {}
    6444};
    6545
     
    6949/// List of candidates
    7050using CandidateList = std::vector< CandidateRef >;
    71 
    72 /// Splice src after dst, clearing src
    73 static inline void splice( CandidateList & dst, CandidateList & src ) {
    74         dst.reserve( dst.size() + src.size() );
    75         for ( CandidateRef & r : src ) { dst.emplace_back( std::move( r ) ); }
    76         src.clear();
    77 }
    78 
    79 /// Splice src before dst
    80 static inline void spliceBegin( CandidateList & dst, CandidateList & src ) {
    81         splice( src, dst );
    82         dst.swap( src );
    83 }
    84 
    85 /// Sum the cost of a list of candidates
    86 static inline Cost sumCost( const CandidateList & candidates ) {
    87         Cost total = Cost::zero;
    88         for ( const CandidateRef & r : candidates ) { total += r->cost; }
    89         return total;
    90 }
    91 
    92 /// Holdover behaviour from old `findMinCost` -- xxx -- can maybe be eliminated?
    93 static inline void promoteCvtCost( CandidateList & candidates ) {
    94         for ( CandidateRef & r : candidates ) {
    95                 r->cost = r->cvtCost;
    96         }
    97 }
    9851
    9952void print( std::ostream & os, const Candidate & cand, Indenter indent = {} );
  • src/ResolvExpr/CandidateFinder.cpp

    r21300d7 raaeacf4  
    1616#include "CandidateFinder.hpp"
    1717
    18 #include <deque>
    19 #include <iterator>               // for back_inserter
    20 #include <sstream>
    21 #include <string>
    22 #include <unordered_map>
    23 #include <vector>
    24 
    25 #include "Candidate.hpp"
    26 #include "CompilationState.h"
    27 #include "Cost.h"
    28 #include "ExplodedArg.hpp"
    29 #include "Resolver.h"
    30 #include "SatisfyAssertions.hpp"
    31 #include "typeops.h"              // for adjustExprType
    32 #include "Unify.h"
    3318#include "AST/Expr.hpp"
    34 #include "AST/Node.hpp"
    35 #include "AST/Pass.hpp"
    36 #include "AST/Print.hpp"
    37 #include "AST/SymbolTable.hpp"
    38 #include "AST/Type.hpp"
    39 #include "SymTab/Mangler.h"
    40 #include "Tuples/Tuples.h"        // for handleTupleAssignment
    41 
    42 #define PRINT( text ) if ( resolvep ) { text }
    4319
    4420namespace ResolvExpr {
    4521
    46 namespace {
    47 
    48         /// First index is which argument, second is which alternative, third is which exploded element
    49         using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;
    50 
    51         /// Returns a list of alternatives with the minimum cost in the given list
    52         CandidateList findMinCost( const CandidateList & candidates ) {
    53                 CandidateList out;
    54                 Cost minCost = Cost::infinity;
    55                 for ( const CandidateRef & r : candidates ) {
    56                         if ( r->cost < minCost ) {
    57                                 minCost = r->cost;
    58                                 out.clear();
    59                                 out.emplace_back( r );
    60                         } else if ( r->cost == minCost ) {
    61                                 out.emplace_back( r );
    62                         }
    63                 }
    64                 return out;
    65         }
    66 
    67         /// Computes conversion cost for a given candidate
    68         Cost computeApplicationConversionCost(
    69                 const CandidateRef & cand, const ast::SymbolTable & symtab
    70         ) {
    71                 #warning unimplemented
    72                 (void)cand; (void)symtab;
    73                 assert(false);
    74                 return Cost::infinity;
    75         }
    76 
    77         /// Actually visits expressions to find their candidate interpretations
    78         struct Finder final : public ast::WithShortCircuiting {
    79                 CandidateFinder & selfFinder;
    80                 const ast::SymbolTable & symtab;
    81                 CandidateList & candidates;
    82                 const ast::TypeEnvironment & tenv;
    83                 ast::ptr< ast::Type > & targetType;
    84 
    85                 Finder( CandidateFinder & f )
    86                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
    87                   targetType( f.targetType ) {}
    88                
    89                 void previsit( const ast::Node * ) { visit_children = false; }
    90 
    91                 /// Convenience to add candidate to list
    92                 template<typename... Args>
    93                 void addCandidate( Args &&... args ) {
    94                         candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
    95                 }
    96 
    97                 void postvisit( const ast::ApplicationExpr * applicationExpr ) {
    98                         addCandidate( applicationExpr, tenv );
    99                 }
    100 
    101                 /// Builds a list of candidates for a function, storing them in out
    102                 void makeFunctionCandidates(
    103                         const CandidateRef & func, const ast::FunctionType * funcType,
    104                         const ExplodedArgs_new & args, CandidateList & out
    105                 ) {
    106                         #warning unimplemented
    107                         (void)func; (void)funcType; (void)args; (void)out;
    108                         assert(false);
    109                 }
    110 
    111                 /// Adds implicit struct-conversions to the alternative list
    112                 void addAnonConversions( const CandidateRef & cand ) {
    113                         #warning unimplemented
    114                         (void)cand;
    115                         assert(false);
    116                 }
    117 
    118                 void postvisit( const ast::UntypedExpr * untypedExpr ) {
    119                         CandidateFinder funcFinder{ symtab, tenv };
    120                         funcFinder.find( untypedExpr->func, ResolvMode::withAdjustment() );
    121                         // short-circuit if no candidates
    122                         if ( funcFinder.candidates.empty() ) return;
    123 
    124                         std::vector< CandidateFinder > argCandidates =
    125                                 selfFinder.findSubExprs( untypedExpr->args );
    126                        
    127                         // take care of possible tuple assignments
    128                         // if not tuple assignment, handled as normal function call
    129                         Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );
    130 
    131                         // find function operators
    132                         ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" };
    133                         CandidateFinder opFinder{ symtab, tenv };
    134                         // okay if there aren't any function operations
    135                         opFinder.find( opExpr, ResolvMode::withoutFailFast() );
    136                         PRINT(
    137                                 std::cerr << "known function ops:" << std::endl;
    138                                 print( std::cerr, opFinder.candidates, 1 );
    139                         )
    140 
    141                         // pre-explode arguments
    142                         ExplodedArgs_new argExpansions;
    143                         for ( const CandidateFinder & args : argCandidates ) {
    144                                 argExpansions.emplace_back();
    145                                 auto & argE = argExpansions.back();
    146                                 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); }
    147                         }
    148 
    149                         // Find function matches
    150                         CandidateList found;
    151                         SemanticErrorException errors;
    152                         for ( CandidateRef & func : funcFinder ) {
    153                                 try {
    154                                         PRINT(
    155                                                 std::cerr << "working on alternative:" << std::endl;
    156                                                 print( std::cerr, *func, 2 );
    157                                         )
    158 
    159                                         // check if the type is a pointer to function
    160                                         const ast::Type * funcResult = func->expr->result->stripReferences();
    161                                         if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) {
    162                                                 if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    163                                                         CandidateRef newFunc{ new Candidate{ *func } };
    164                                                         newFunc->expr =
    165                                                                 referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    166                                                         makeFunctionCandidates( newFunc, function, argExpansions, found );
    167                                                 }
    168                                         } else if (
    169                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    170                                         ) {
    171                                                 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    172                                                         if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    173                                                                 CandidateRef newFunc{ new Candidate{ *func } };
    174                                                                 newFunc->expr =
    175                                                                         referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    176                                                                 makeFunctionCandidates( newFunc, function, argExpansions, found );
    177                                                         }
    178                                                 }
    179                                         }
    180                                 } catch ( SemanticErrorException & e ) { errors.append( e ); }
    181                         }
    182 
    183                         // Find matches on function operators `?()`
    184                         if ( ! opFinder.candidates.empty() ) {
    185                                 // add exploded function alternatives to front of argument list
    186                                 std::vector< ExplodedArg > funcE;
    187                                 funcE.reserve( funcFinder.candidates.size() );
    188                                 for ( const CandidateRef & func : funcFinder ) {
    189                                         funcE.emplace_back( *func, symtab );
    190                                 }
    191                                 argExpansions.emplace_front( std::move( funcE ) );
    192 
    193                                 for ( const CandidateRef & op : opFinder ) {
    194                                         try {
    195                                                 // check if type is pointer-to-function
    196                                                 const ast::Type * opResult = op->expr->result->stripReferences();
    197                                                 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) {
    198                                                         if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    199                                                                 CandidateRef newOp{ new Candidate{ *op} };
    200                                                                 newOp->expr =
    201                                                                         referenceToRvalueConversion( newOp->expr, newOp->cost );
    202                                                                 makeFunctionCandidates( newOp, function, argExpansions, found );
    203                                                         }
    204                                                 }
    205                                         } catch ( SemanticErrorException & e ) { errors.append( e ); }
    206                                 }
    207                         }
    208 
    209                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    210                         // candidates
    211                         if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
    212 
    213                         // Compute conversion costs
    214                         for ( CandidateRef & withFunc : found ) {
    215                                 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );
    216 
    217                                 PRINT(
    218                                         auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();
    219                                         auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    220                                         auto function = pointer->base.strict_as< ast::FunctionType >();
    221                                        
    222                                         std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    223                                         std::cerr << "parameters are:" << std::endl;
    224                                         ast::printAll( std::cerr, function->params, 2 );
    225                                         std::cerr << "arguments are:" << std::endl;
    226                                         ast::printAll( std::cerr, appExpr->args, 2 );
    227                                         std::cerr << "bindings are:" << std::endl;
    228                                         ast::print( std::cerr, withFunc->env, 2 );
    229                                         std::cerr << "cost is: " << withFunc->cost << std::endl;
    230                                         std::cerr << "cost of conversion is:" << cvtCost << std::endl;
    231                                 )
    232 
    233                                 if ( cvtCost != Cost::infinity ) {
    234                                         withFunc->cvtCost = cvtCost;
    235                                         candidates.emplace_back( std::move( withFunc ) );
    236                                 }
    237                         }
    238                         found = std::move( candidates );
    239 
    240                         // use a new list so that candidates are not examined by addAnonConversions twice
    241                         CandidateList winners = findMinCost( found );
    242                         promoteCvtCost( winners );
    243 
    244                         // function may return a struct/union value, in which case we need to add candidates
    245                         // for implicit conversions to each of the anonymous members, which must happen after
    246                         // `findMinCost`, since anon conversions are never the cheapest
    247                         for ( const CandidateRef & c : winners ) {
    248                                 addAnonConversions( c );
    249                         }
    250                         spliceBegin( candidates, winners );
    251 
    252                         if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    253                                 // If resolution is unsuccessful with a target type, try again without, since it
    254                                 // will sometimes succeed when it wouldn't with a target type binding.
    255                                 // For example:
    256                                 //   forall( otype T ) T & ?[]( T *, ptrdiff_t );
    257                                 //   const char * x = "hello world";
    258                                 //   unsigned char ch = x[0];
    259                                 // Fails with simple return type binding (xxx -- check this!) as follows:
    260                                 // * T is bound to unsigned char
    261                                 // * (x: const char *) is unified with unsigned char *, which fails
    262                                 // xxx -- fix this better
    263                                 targetType = nullptr;
    264                                 postvisit( untypedExpr );
    265                         }
    266                 }
    267 
    268                 /// true if expression is an lvalue
    269                 static bool isLvalue( const ast::Expr * x ) {
    270                         return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
    271                 }
    272 
    273                 void postvisit( const ast::AddressExpr * addressExpr ) {
    274                         CandidateFinder finder{ symtab, tenv };
    275                         finder.find( addressExpr->arg );
    276                         for ( CandidateRef & r : finder.candidates ) {
    277                                 if ( ! isLvalue( r->expr ) ) continue;
    278                                 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } );
    279                         }
    280                 }
    281 
    282                 void postvisit( const ast::LabelAddressExpr * labelExpr ) {
    283                         addCandidate( labelExpr, tenv );
    284                 }
    285 
    286                 void postvisit( const ast::CastExpr * castExpr ) {
    287                         #warning unimplemented
    288                         (void)castExpr;
    289                         assert(false);
    290                 }
    291 
    292                 void postvisit( const ast::VirtualCastExpr * castExpr ) {
    293                         assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );
    294                         CandidateFinder finder{ symtab, tenv };
    295                         // don't prune here, all alternatives guaranteed to have same type
    296                         finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    297                         for ( CandidateRef & r : finder.candidates ) {
    298                                 addCandidate(
    299                                         *r, new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    300                         }
    301                 }
    302 
    303                 void postvisit( const ast::UntypedMemberExpr * memberExpr ) {
    304                         #warning unimplemented
    305                         (void)memberExpr;
    306                         assert(false);
    307                 }
    308 
    309                 void postvisit( const ast::MemberExpr * memberExpr ) {
    310                         addCandidate( memberExpr, tenv );
    311                 }
    312 
    313                 void postvisit( const ast::NameExpr * variableExpr ) {
    314                         #warning unimplemented
    315                         (void)variableExpr;
    316                         assert(false);
    317                 }
    318 
    319                 void postvisit( const ast::VariableExpr * variableExpr ) {
    320                         // not sufficient to just pass `variableExpr` here, type might have changed since
    321                         // creation
    322                         addCandidate(
    323                                 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    324                 }
    325 
    326                 void postvisit( const ast::ConstantExpr * constantExpr ) {
    327                         addCandidate( constantExpr, tenv );
    328                 }
    329 
    330                 void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    331                         #warning unimplemented
    332                         (void)sizeofExpr;
    333                         assert(false);
    334                 }
    335 
    336                 void postvisit( const ast::AlignofExpr * alignofExpr ) {
    337                         #warning unimplemented
    338                         (void)alignofExpr;
    339                         assert(false);
    340                 }
    341 
    342                 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
    343                         #warning unimplemented
    344                         (void)offsetofExpr;
    345                         assert(false);
    346                 }
    347 
    348                 void postvisit( const ast::OffsetofExpr * offsetofExpr ) {
    349                         addCandidate( offsetofExpr, tenv );
    350                 }
    351 
    352                 void postvisit( const ast::OffsetPackExpr * offsetPackExpr ) {
    353                         addCandidate( offsetPackExpr, tenv );
    354                 }
    355 
    356                 void postvisit( const ast::LogicalExpr * logicalExpr ) {
    357                         CandidateFinder finder1{ symtab, tenv };
    358                         finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );
    359                         if ( finder1.candidates.empty() ) return;
    360 
    361                         CandidateFinder finder2{ symtab, tenv };
    362                         finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    363                         if ( finder2.candidates.empty() ) return;
    364 
    365                         for ( const CandidateRef & r1 : finder1.candidates ) {
    366                                 for ( const CandidateRef & r2 : finder2.candidates ) {
    367                                         ast::TypeEnvironment env{ r1->env };
    368                                         env.simpleCombine( r2->env );
    369                                         ast::OpenVarSet open{ r1->open };
    370                                         mergeOpenVars( open, r2->open );
    371                                         ast::AssertionSet need;
    372                                         mergeAssertionSet( need, r1->need );
    373                                         mergeAssertionSet( need, r2->need );
    374 
    375                                         addCandidate(
    376                                                 new ast::LogicalExpr{
    377                                                         logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    378                                                 std::move( env ), std::move( open ), std::move( need ),
    379                                                 r1->cost + r2->cost );
    380                                 }
    381                         }
    382                 }
    383 
    384                 void postvisit( const ast::ConditionalExpr * conditionalExpr ) {
    385                         // candidates for condition
    386                         CandidateFinder finder1{ symtab, tenv };
    387                         finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );
    388                         if ( finder1.candidates.empty() ) return;
    389 
    390                         // candidates for true result
    391                         CandidateFinder finder2{ symtab, tenv };
    392                         finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );
    393                         if ( finder2.candidates.empty() ) return;
    394 
    395                         // candidates for false result
    396                         CandidateFinder finder3{ symtab, tenv };
    397                         finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    398                         if ( finder3.candidates.empty() ) return;
    399 
    400                         for ( const CandidateRef & r1 : finder1.candidates ) {
    401                                 for ( const CandidateRef & r2 : finder2.candidates ) {
    402                                         for ( const CandidateRef & r3 : finder3.candidates ) {
    403                                                 ast::TypeEnvironment env{ r1->env };
    404                                                 env.simpleCombine( r2->env );
    405                                                 env.simpleCombine( r3->env );
    406                                                 ast::OpenVarSet open{ r1->open };
    407                                                 mergeOpenVars( open, r2->open );
    408                                                 mergeOpenVars( open, r3->open );
    409                                                 ast::AssertionSet need;
    410                                                 mergeAssertionSet( need, r1->need );
    411                                                 mergeAssertionSet( need, r2->need );
    412                                                 mergeAssertionSet( need, r3->need );
    413                                                 ast::AssertionSet have;
    414 
    415                                                 // unify true and false results, then infer parameters to produce new
    416                                                 // candidates
    417                                                 ast::ptr< ast::Type > common;
    418                                                 if (
    419                                                         unify(
    420                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab,
    421                                                                 common )
    422                                                 ) {
    423                                                         #warning unimplemented
    424                                                         assert(false);
    425                                                 }
    426                                         }
    427                                 }
    428                         }
    429                 }
    430 
    431                 void postvisit( const ast::CommaExpr * commaExpr ) {
    432                         ast::TypeEnvironment env{ tenv };
    433                         ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    434                        
    435                         CandidateFinder finder2{ symtab, env };
    436                         finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
    437 
    438                         for ( const CandidateRef & r2 : finder2.candidates ) {
    439                                 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } );
    440                         }
    441                 }
    442 
    443                 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) {
    444                         addCandidate( ctorExpr, tenv );
    445                 }
    446 
    447                 void postvisit( const ast::ConstructorExpr * ctorExpr ) {
    448                         CandidateFinder finder{ symtab, tenv };
    449                         finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );
    450                         for ( CandidateRef & r : finder.candidates ) {
    451                                 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } );
    452                         }
    453                 }
    454 
    455                 void postvisit( const ast::RangeExpr * rangeExpr ) {
    456                         // resolve low and high, accept candidates where low and high types unify
    457                         CandidateFinder finder1{ symtab, tenv };
    458                         finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );
    459                         if ( finder1.candidates.empty() ) return;
    460 
    461                         CandidateFinder finder2{ symtab, tenv };
    462                         finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    463                         if ( finder2.candidates.empty() ) return;
    464 
    465                         for ( const CandidateRef & r1 : finder1.candidates ) {
    466                                 for ( const CandidateRef & r2 : finder2.candidates ) {
    467                                         ast::TypeEnvironment env{ r1->env };
    468                                         env.simpleCombine( r2->env );
    469                                         ast::OpenVarSet open{ r1->open };
    470                                         mergeOpenVars( open, r2->open );
    471                                         ast::AssertionSet need;
    472                                         mergeAssertionSet( need, r1->need );
    473                                         mergeAssertionSet( need, r2->need );
    474                                         ast::AssertionSet have;
    475 
    476                                         ast::ptr< ast::Type > common;
    477                                         if (
    478                                                 unify(
    479                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab,
    480                                                         common )
    481                                         ) {
    482                                                 ast::RangeExpr * newExpr =
    483                                                         new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    484                                                 newExpr->result = common ? common : r1->expr->result;
    485                                                
    486                                                 #warning unimplemented
    487                                                 assert(false);
    488                                         }
    489                                 }
    490                         }
    491                 }
    492 
    493                 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    494                         std::vector< CandidateFinder > subCandidates =
    495                                 selfFinder.findSubExprs( tupleExpr->exprs );
    496                         std::vector< CandidateList > possibilities;
    497                         combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) );
    498 
    499                         for ( const CandidateList & subs : possibilities ) {
    500                                 std::vector< ast::ptr< ast::Expr > > exprs;
    501                                 exprs.reserve( subs.size() );
    502                                 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); }
    503 
    504                                 ast::TypeEnvironment env;
    505                                 ast::OpenVarSet open;
    506                                 ast::AssertionSet need;
    507                                 for ( const CandidateRef & sub : subs ) {
    508                                         env.simpleCombine( sub->env );
    509                                         mergeOpenVars( open, sub->open );
    510                                         mergeAssertionSet( need, sub->need );
    511                                 }
    512 
    513                                 addCandidate(
    514                                         new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },
    515                                         std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );
    516                         }
    517                 }
    518 
    519                 void postvisit( const ast::TupleExpr * tupleExpr ) {
    520                         addCandidate( tupleExpr, tenv );
    521                 }
    522 
    523                 void postvisit( const ast::TupleIndexExpr * tupleExpr ) {
    524                         addCandidate( tupleExpr, tenv );
    525                 }
    526 
    527                 void postvisit( const ast::TupleAssignExpr * tupleExpr ) {
    528                         addCandidate( tupleExpr, tenv );
    529                 }
    530 
    531                 void postvisit( const ast::UniqueExpr * unqExpr ) {
    532                         CandidateFinder finder{ symtab, tenv };
    533                         finder.find( unqExpr->expr, ResolvMode::withAdjustment() );
    534                         for ( CandidateRef & r : finder.candidates ) {
    535                                 // ensure that the the id is passed on so that the expressions are "linked"
    536                                 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } );
    537                         }
    538                 }
    539 
    540                 void postvisit( const ast::StmtExpr * stmtExpr ) {
    541                         #warning unimplemented
    542                         (void)stmtExpr;
    543                         assert(false);
    544                 }
    545 
    546                 void postvisit( const ast::UntypedInitExpr * initExpr ) {
    547                         #warning unimplemented
    548                         (void)initExpr;
    549                         assert(false);
    550                 }
    551 
    552                 void postvisit( const ast::InitExpr * ) {
    553                         assertf( false, "CandidateFinder should never see a resolved InitExpr." );
    554                 }
    555 
    556                 void postvisit( const ast::DeletedExpr * ) {
    557                         assertf( false, "CandidateFinder should never see a DeletedExpr." );
    558                 }
    559 
    560                 void postvisit( const ast::GenericExpr * ) {
    561                         assertf( false, "_Generic is not yet supported." );
    562                 }
    563         };
    564 
    565         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    566         /// return type. Skips ambiguous candidates.
    567         CandidateList pruneCandidates( CandidateList & candidates ) {
    568                 struct PruneStruct {
    569                         CandidateRef candidate;
    570                         bool ambiguous;
    571 
    572                         PruneStruct() = default;
    573                         PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
    574                 };
    575 
    576                 // find lowest-cost candidate for each type
    577                 std::unordered_map< std::string, PruneStruct > selected;
    578                 for ( CandidateRef & candidate : candidates ) {
    579                         std::string mangleName;
    580                         {
    581                                 ast::ptr< ast::Type > newType = candidate->expr->result;
    582                                 candidate->env.apply( newType );
    583                                 mangleName = Mangle::mangle( newType );
    584                         }
    585 
    586                         auto found = selected.find( mangleName );
    587                         if ( found != selected.end() ) {
    588                                 if ( candidate->cost < found->second.candidate->cost ) {
    589                                         PRINT(
    590                                                 std::cerr << "cost " << candidate->cost << " beats "
    591                                                         << found->second.candidate->cost << std::endl;
    592                                         )
    593 
    594                                         found->second = PruneStruct{ candidate };
    595                                 } else if ( candidate->cost == found->second.candidate->cost ) {
    596                                         // if one of the candidates contains a deleted identifier, can pick the other,
    597                                         // since deleted expressions should not be ambiguous if there is another option
    598                                         // that is at least as good
    599                                         if ( findDeletedExpr( candidate->expr ) ) {
    600                                                 // do nothing
    601                                                 PRINT( std::cerr << "candidate is deleted" << std::endl; )
    602                                         } else if ( findDeletedExpr( found->second.candidate->expr ) ) {
    603                                                 PRINT( std::cerr << "current is deleted" << std::endl; )
    604                                                 found->second = PruneStruct{ candidate };
    605                                         } else {
    606                                                 PRINT( std::cerr << "marking ambiguous" << std::endl; )
    607                                                 found->second.ambiguous = true;
    608                                         }
    609                                 } else {
    610                                         PRINT(
    611                                                 std::cerr << "cost " << candidate->cost << " loses to "
    612                                                         << found->second.candidate->cost << std::endl;
    613                                         )
    614                                 }
    615                         } else {
    616                                 selected.emplace_hint( found, mangleName, candidate );
    617                         }
    618                 }
    619 
    620                 // report unambiguous min-cost candidates
    621                 CandidateList out;
    622                 for ( auto & target : selected ) {
    623                         if ( target.second.ambiguous ) continue;
    624 
    625                         CandidateRef cand = target.second.candidate;
    626                        
    627                         ast::ptr< ast::Type > newResult = cand->expr->result;
    628                         cand->env.applyFree( newResult );
    629                         cand->expr = ast::mutate_field(
    630                                 cand->expr.get(), &ast::Expr::result, std::move( newResult ) );
    631                        
    632                         out.emplace_back( cand );
    633                 }
    634                 return out;
    635         }
    636 
    637 } // anonymous namespace
    638 
    63922void 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);
    73726}
    73827
  • src/ResolvExpr/CandidateFinder.hpp

    r21300d7 raaeacf4  
    1919#include "ResolvMode.h"
    2020#include "AST/Fwd.hpp"
    21 #include "AST/Node.hpp"
    2221#include "AST/SymbolTable.hpp"
    2322#include "AST/TypeEnvironment.hpp"
     
    3029        const ast::SymbolTable & symtab;         ///< Symbol table to lookup candidates
    3130        const ast::TypeEnvironment & env;        ///< Substitutions performed in this resolution
    32         ast::ptr< ast::Type > targetType = nullptr;  ///< Target type for resolution
     31        const ast::Type * targetType = nullptr;  ///< Target type for resolution
    3332
    3433        CandidateFinder( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env )
     
    3736        /// Fill candidates with feasible resolutions for `expr`
    3837        void find( const ast::Expr * expr, ResolvMode mode = {} );
    39 
    40         /// Runs new candidate finder on each element in xs, returning the list of finders
    41         std::vector< CandidateFinder > findSubExprs( const std::vector< ast::ptr< ast::Expr > > & xs );
    42 
    43         using value_type = CandidateList::value_type;
    44         using iterator = CandidateList::iterator;
    45         using const_iterator = CandidateList::const_iterator;
    46 
    47         iterator begin() { return candidates.begin(); }
    48         const_iterator begin() const { return candidates.begin(); }
    49        
    50         iterator end() { return candidates.end(); }
    51         const_iterator end() const { return candidates.end(); }
    5238};
    5339
  • src/ResolvExpr/CurrentObject.cc

    r21300d7 raaeacf4  
    946946        }
    947947
    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 ) {
    1022949                PRINT( std::cerr << "____setNext" << designation << std::endl; )
    1023950                assertf( ! objStack.empty(), "obj stack empty in setNext" );
  • src/ResolvExpr/CurrentObject.h

    r21300d7 raaeacf4  
    111111                CurrentObject( const CodeLocation & loc, const Type * type );
    112112
    113                 /// resolves unresolved designation
    114                 const Designation * findNext( const Designation * designation );
    115113                /// sets current position using the resolved designation
    116114                void setNext( const ast::Designation * designation );
  • src/ResolvExpr/ExplodedActual.cc

    r21300d7 raaeacf4  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ExplodedActual.cc --
     7// Alternative.h --
    88//
    99// Author           : Aaron B. Moss
     
    2424        }
    2525}
    26 
    27 // Local Variables: //
    28 // tab-width: 4 //
    29 // mode: c++ //
    30 // compile-command: "make install" //
    31 // End: //
  • src/ResolvExpr/ExplodedActual.h

    r21300d7 raaeacf4  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ExplodedActual.h --
     7// Alternative.h --
    88//
    99// Author           : Aaron B. Moss
     
    3737        };
    3838}
    39 
    40 // Local Variables: //
    41 // tab-width: 4 //
    42 // mode: c++ //
    43 // compile-command: "make install" //
    44 // End: //
  • src/ResolvExpr/ResolvMode.h

    r21300d7 raaeacf4  
    2222                const bool prune;            ///< Prune alternatives to min-cost per return type? [true]
    2323                const bool failFast;         ///< Fail on no resulting alternatives? [true]
    24                 const bool satisfyAssns;     ///< Satisfy assertions? [false]
     24                const bool resolveAssns;     ///< Resolve assertions? [false]
    2525
    2626        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) {}
    2929
    3030        public:
    3131                /// Default settings
    32                 constexpr ResolvMode() : adjust(false), prune(true), failFast(true), satisfyAssns(false) {}
     32                constexpr ResolvMode() : adjust(false), prune(true), failFast(true), resolveAssns(false) {}
    3333               
    3434                /// With adjust flag set; turns array and function types into equivalent pointers
     
    4343                static constexpr ResolvMode withoutFailFast() { return { true, true, false, false }; }
    4444
    45                 /// The same mode, but with satisfyAssns turned on; for top-level calls
     45                /// The same mode, but with resolveAssns turned on; for top-level calls
    4646                ResolvMode atTopLevel() const { return { adjust, prune, failFast, true }; }
    4747        };
  • src/ResolvExpr/Resolver.cc

    r21300d7 raaeacf4  
    3535#include "AST/Print.hpp"
    3636#include "AST/SymbolTable.hpp"
    37 #include "AST/Type.hpp"
    3837#include "Common/PassVisitor.h"          // for PassVisitor
    3938#include "Common/SemanticError.h"        // for SemanticError
     
    957956                        }
    958957                };
    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
    969966                /// always-accept candidate filter
    970967                bool anyCandidate( const Candidate & ) { return true; }
     
    10261023
    10271024                        // promote candidate.cvtCost to .cost
    1028                         promoteCvtCost( winners );
     1025                        for ( CandidateRef & cand : winners ) {
     1026                                cand->cost = cand->cvtCost;
     1027                        }
    10291028
    10301029                        // produce ambiguous errors, if applicable
     
    11001099                        StripCasts_new::strip( expr );
    11011100                }
    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
    11241122                /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    11251123                /// context.
     
    11481146                }
    11491147
    1150                 /// Resolve `untyped` to the single expression whose candidate is the best match
    1151                 ast::ptr< ast::Expr > findSingleExpression(
    1152                         const ast::Expr * untyped, const ast::SymbolTable & symtab
    1153                 ) {
    1154                         return findKindExpression( untyped, symtab );
    1155                 }
    1156 
    11571148                /// Resolve `untyped` to the single expression whose candidate is the best match for the
    11581149                /// given type.
     
    11611152                ) {
    11621153                        assert( untyped && type );
    1163                         ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped->location, untyped, type };
    1164                         ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
     1154                        const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
     1155                        ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab );
    11651156                        removeExtraneousCast( newExpr, symtab );
    11661157                        return newExpr;
     
    11981189                        return false;
    11991190                }
    1200 
    1201                 /// Advance a type itertor to the next mutex parameter
    1202                 template<typename Iter>
    1203                 inline bool nextMutex( Iter & it, const Iter & end ) {
    1204                         while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
    1205                         return it != end;
    1206                 }
    12071191        }
    12081192
     
    12291213                void previsit( const ast::PointerType * );
    12301214
    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 * );
    12481232        };
    12491233
     
    13971381                                "expression." );
    13981382                       
    1399                         ast::ptr< ast::Expr > untyped =
     1383                        const ast::Expr * untyped =
    14001384                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1401                         ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
     1385                        ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab );
    14021386                       
    14031387                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     
    14171401                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    14181402                        // computed goto argument is void*
    1419                         ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
    14201403                        branchStmt = ast::mutate_field(
    14211404                                branchStmt, &ast::BranchStmt::computedTarget,
    1422                                 findSingleExpression( branchStmt->computedTarget, target, symtab ) );
     1405                                findSingleExpression(
     1406                                        branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} },
     1407                                        symtab ) );
    14231408                }
    14241409                return branchStmt;
     
    14601445        }
    14611446
    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);
    17121451        }
    17131452
     
    17181457                // resolve initialization using the possibilities as determined by the `currentObject`
    17191458                // cursor.
    1720                 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
     1459                ast::Expr * untyped = new ast::UntypedInitExpr{
    17211460                        singleInit->location, singleInit->value, currentObject.getOptions() };
    1722                 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
     1461                ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab );
    17231462                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    17241463
     
    17711510                        // iterate designations and initializers in pairs, moving the cursor to the current
    17721511                        // 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                }
    17831515
    17841516                visit_children = false;
     
    17861518        }
    17871519
    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);
    18071524        }
    18081525
  • src/ResolvExpr/Resolver.h

    r21300d7 raaeacf4  
    1717
    1818#include <list>          // for list
    19 
    20 #include "AST/Node.hpp"  // for ptr
     19#include <AST/Node.hpp>  // for ptr
    2120
    2221class ConstructorInit;
     
    3029namespace ast {
    3130        class Decl;
    32         class DeletedExpr;
    33         class SymbolTable;
    34         class TypeEnvironment;
    3531} // namespace ast
    3632
     
    5248        /// Checks types and binds syntactic constructs to typed representations
    5349        void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit );
    54         /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
    55         const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr );
    56         /// Find the expression candidate that is the unique best match for `untyped` in a `void`
    57         /// context.
    58         ast::ptr< ast::Expr > resolveInVoidContext(
    59                 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
    6050} // namespace ResolvExpr
    6151
  • src/ResolvExpr/Unify.cc

    r21300d7 raaeacf4  
    11431143                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11441144                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1145                         ast::OpenVarSet & open, const ast::SymbolTable & symtab
    1146         ) {
    1147                 ast::ptr<ast::Type> common;
    1148                 return unify( type1, type2, env, need, have, open, symtab, common );
    1149         }
    1150 
    1151         bool unify(
    1152                         const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    1153                         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    11541145                        ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
    11551146        ) {
  • src/ResolvExpr/Unify.h

    r21300d7 raaeacf4  
    7272                const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    7373                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,
    7974                ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
    8075
  • src/ResolvExpr/module.mk

    r21300d7 raaeacf4  
    2626      ResolvExpr/CurrentObject.cc \
    2727      ResolvExpr/ExplodedActual.cc \
    28       ResolvExpr/ExplodedArg.cpp \
    2928      ResolvExpr/FindOpenVars.cc \
    3029      ResolvExpr/Occurs.cc \
     
    3635      ResolvExpr/Resolver.cc \
    3736      ResolvExpr/ResolveTypeof.cc \
    38       ResolvExpr/SatisfyAssertions.cpp \
    3937      ResolvExpr/SpecCost.cc \
    4038      ResolvExpr/TypeEnvironment.cc \
  • src/ResolvExpr/typeops.h

    r21300d7 raaeacf4  
    7171                } // while
    7272        }
    73 
    74         /// Replaces array types with equivalent pointer, and function types with a pointer-to-function
    75         const ast::Type * adjustExprType(
    76                 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );
    7773
    7874        // in CastCost.cc
  • src/Tuples/Explode.h

    r21300d7 raaeacf4  
    1919#include <utility>                      // for forward
    2020
    21 #include "AST/Expr.hpp"
    2221#include "ResolvExpr/Alternative.h"     // for Alternative, AltList
    23 #include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
    2422#include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
    25 #include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
    2623#include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
    2724#include "SynTree/Type.h"               // for TupleType, Type
    2825#include "Tuples.h"                     // for maybeImpure
    29 
    30 namespace ast {
    31         class SymbolTable;
    32 }
    3326
    3427namespace SymTab {
     
    137130                explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
    138131        }
    139 
    140 /// helper function used by explode
    141 template< typename Output >
    142 void explodeUnique(
    143         const ast::Expr * expr, const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab,
    144         Output && out, bool isTupleAssign
    145 ) {
    146         #warning unimplemented
    147         (void)expr; (void)arg; (void)symtab; (void)out; (void)isTupleAssign;
    148         assert(false);
    149 }
    150 
    151 /// expands a tuple-valued candidate into multiple candidates, each with a non-tuple type
    152 template< typename Output >
    153 void explode(
    154         const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out,
    155         bool isTupleAssign = false
    156 ) {
    157         explodeUnique( arg.expr, arg, symtab, std::forward< Output >( out ), isTupleAssign );
    158 }
    159 
    160132} // namespace Tuples
    161133
  • src/Tuples/TupleAssignment.cc

    r21300d7 raaeacf4  
    377377                }
    378378        }
    379 
    380         void handleTupleAssignment(
    381                 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
    382                 std::vector< ResolvExpr::CandidateFinder > & args
    383         ) {
    384                 #warning unimplmented
    385                 (void)finder; (void)assign; (void)args;
    386                 assert(false);
    387         }
    388379} // namespace Tuples
    389380
  • src/Tuples/Tuples.h

    r21300d7 raaeacf4  
    2626
    2727#include "ResolvExpr/AlternativeFinder.h"
    28 #include "ResolvExpr/CandidateFinder.hpp"
    2928
    3029namespace Tuples {
     
    3231        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign,
    3332                std::vector< ResolvExpr::AlternativeFinder >& args );
    34         void handleTupleAssignment(
    35                 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
    36                 std::vector< ResolvExpr::CandidateFinder > & args );
    3733
    3834        // TupleExpansion.cc
  • tests/sum.cfa

    r21300d7 raaeacf4  
    1111// Created On       : Wed May 27 17:56:53 2015
    1212// Last Modified By : Peter A. Buhr
    13 // Last Modified On : Thu Jun  6 16:18:22 2019
    14 // Update Count     : 333
     13// Last Modified On : Sun May 19 11:21:02 2019
     14// Update Count     : 330
    1515//
    1616
     
    111111        };
    112112        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
    115114        s = 0; v = low;
    116115        for ( int i = 0; i < size; i += 1, v += 1 ) {
Note: See TracChangeset for help on using the changeset viewer.