Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    rc71b256 rd55d7a6  
    105105        }
    106106
    107         namespace {
    108                 struct DeleteFinder : public WithShortCircuiting        {
    109                         DeletedExpr * delExpr = nullptr;
    110                         void previsit( DeletedExpr * expr ) {
    111                                 if ( delExpr ) visit_children = false;
    112                                 else delExpr = expr;
    113                         }
    114 
    115                         void previsit( Expression * ) {
    116                                 if ( delExpr ) visit_children = false;
    117                         }
    118                 };
    119         }
    120 
    121         DeletedExpr * findDeletedExpr( Expression * expr ) {
    122                 PassVisitor<DeleteFinder> finder;
    123                 expr->accept( finder );
    124                 return finder.pass.delExpr;
     107        // used in resolveTypeof
     108        Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
     109                TypeEnvironment env;
     110                return resolveInVoidContext( expr, indexer, env );
    125111        }
    126112
     
    144130        } // namespace
    145131
    146         namespace {
    147                 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
    148                         assertf( untyped, "expected a non-null expression." );
    149                         TypeEnvironment env;
    150                         AlternativeFinder finder( indexer, env );
    151                         finder.find( untyped, adjust, prune, failFast );
    152 
    153                         #if 0
    154                         if ( finder.get_alternatives().size() != 1 ) {
    155                                 std::cerr << "untyped expr is ";
    156                                 untyped->print( std::cerr );
    157                                 std::cerr << std::endl << "alternatives are:";
    158                                 for ( const Alternative & alt : finder.get_alternatives() ) {
    159                                         alt.print( std::cerr );
    160                                 } // for
    161                         } // if
    162                         #endif
    163 
    164                         AltList candidates;
    165                         for ( Alternative & alt : finder.get_alternatives() ) {
    166                                 if ( pred( alt ) ) {
    167                                         candidates.push_back( std::move( alt ) );
    168                                 }
    169                         }
    170 
    171                         // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
    172                         // choose the lowest cost expression among the candidates
    173                         AltList winners;
    174                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    175                         if ( winners.size() == 0 ) {
    176                                 throw SemanticError( toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: "), untyped );
    177                         } else if ( winners.size() != 1 ) {
    178                                 std::ostringstream stream;
    179                                 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
    180                                 untyped->print( stream );
    181                                 stream << "Alternatives are:\n";
    182                                 printAlts( winners, stream, 1 );
    183                                 throw SemanticError( stream.str() );
    184                         }
    185 
    186                         // there is one unambiguous interpretation - move the expression into the with statement
    187                         Alternative & choice = winners.front();
    188                         if ( findDeletedExpr( choice.expr ) ) {
    189                                 throw SemanticError( "Unique best alternative includes deleted identifier in ", choice.expr );
    190                         }
    191                         alt = std::move( choice );
    192                 }
    193 
    194                 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    195                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
    196                         if ( ! untyped ) return;
    197                         Alternative choice;
    198                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
    199                         finishExpr( choice.expr, choice.env, untyped->env );
    200                         delete untyped;
    201                         untyped = choice.expr;
    202                         choice.expr = nullptr;
    203                 }
    204 
    205                 bool standardAlternativeFilter( const Alternative & ) {
    206                         // currently don't need to filter, under normal circumstances.
    207                         // in the future, this may be useful for removing deleted expressions
    208                         return true;
    209                 }
    210         } // namespace
    211 
    212         // used in resolveTypeof
    213         Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
    214                 TypeEnvironment env;
    215                 return resolveInVoidContext( expr, indexer, env );
    216         }
    217 
    218         Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
    219                 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    220                 // interpretations, an exception has already been thrown.
    221                 assertf( expr, "expected a non-null expression." );
    222 
    223                 static CastExpr untyped( nullptr ); // cast to void
    224 
    225                 // set up and resolve expression cast to void
    226                 untyped.arg = expr;
    227                 Alternative choice;
    228                 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
    229                 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    230                 env = std::move( choice.env );
    231 
    232                 // clean up resolved expression
    233                 Expression * ret = castExpr->arg;
    234                 castExpr->arg = nullptr;
    235 
    236                 // unlink the arg so that it isn't deleted twice at the end of the program
    237                 untyped.arg = nullptr;
    238                 return ret;
    239         }
    240 
    241132        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    242133                resetTyVarRenaming();
    243134                TypeEnvironment env;
    244                 Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
     135                Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
    245136                finishExpr( newExpr, env, untyped->env );
    246137                delete untyped;
     
    249140
    250141        void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
    251                 findKindExpression( untyped, indexer, "", standardAlternativeFilter );
     142                if ( ! untyped ) return;
     143                TypeEnvironment env;
     144                AlternativeFinder finder( indexer, env );
     145                finder.find( untyped );
     146                #if 0
     147                if ( finder.get_alternatives().size() != 1 ) {
     148                        std::cerr << "untyped expr is ";
     149                        untyped->print( std::cerr );
     150                        std::cerr << std::endl << "alternatives are:";
     151                        for ( const Alternative & alt : finder.get_alternatives() ) {
     152                                alt.print( std::cerr );
     153                        } // for
     154                } // if
     155                #endif
     156                assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end: (%zd) %s", finder.get_alternatives().size(), toString( untyped ).c_str() );
     157                Alternative &choice = finder.get_alternatives().front();
     158                Expression *newExpr = choice.expr->clone();
     159                finishExpr( newExpr, choice.env, untyped->env );
     160                delete untyped;
     161                untyped = newExpr;
    252162        }
    253163
     
    260170
    261171        namespace {
    262                 bool isIntegralType( const Alternative & alt ) {
    263                         Type * type = alt.expr->result;
     172                /// resolve `untyped` to the expression whose type satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
     173                template<typename Pred>
     174                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, Pred pred) {
     175                        TypeEnvironment env;
     176                        AlternativeFinder finder( indexer, env );
     177                        finder.findWithAdjustment( untyped );
     178
     179                        AltList candidates;
     180                        for ( Alternative & alt : finder.get_alternatives() ) {
     181                                if ( pred( alt.expr->result ) ) {
     182                                        candidates.push_back( std::move( alt ) );
     183                                }
     184                        }
     185
     186                        // choose the lowest cost expression among the candidates
     187                        AltList winners;
     188                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     189                        if ( winners.size() == 0 ) {
     190                                throw SemanticError( untyped, "No reasonable alternatives for " + kindStr + " expression: " );
     191                        } else if ( winners.size() != 1 ) {
     192                                std::ostringstream stream;
     193                                stream << "Cannot choose between " << winners.size() << " alternatives for " + kindStr +  " expression\n";
     194                                untyped->print( stream );
     195                                stream << "Alternatives are:\n";
     196                                printAlts( winners, stream, 1 );
     197                                throw SemanticError( untyped->location, stream.str() );
     198                        }
     199
     200                        // there is one unambiguous interpretation - move the expression into the with statement
     201                        Alternative & alt = winners.front();
     202                        finishExpr( alt.expr, alt.env, untyped->env );
     203                        delete untyped;
     204                        untyped = alt.expr;
     205                        alt.expr = nullptr;
     206                }
     207
     208                bool isIntegralType( Type *type ) {
    264209                        if ( dynamic_cast< EnumInstType * >( type ) ) {
    265210                                return true;
     
    484429                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
    485430                                ss << "' in call to waitfor";
    486                                 throw SemanticError( ss.str() );
     431                                throw SemanticError( stmt->location, ss.str() );
    487432                        }
    488433
     
    506451                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
    507452                                        if( !pointer ) {
    508                                                 throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
     453                                                throw SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
    509454                                        }
    510455
    511456                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
    512457                                        if( !function ) {
    513                                                 throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
     458                                                throw SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
    514459                                        }
    515460
     
    520465
    521466                                                if( !advance_to_mutex( param, param_end ) ) {
    522                                                         throw SemanticError("candidate function not viable: no mutex parameters\n", function);
     467                                                        throw SemanticError(function, "candidate function not viable: no mutex parameters\n");
    523468                                                }
    524469                                        }
     
    559504                                                                        // We ran out of parameters but still have arguments
    560505                                                                        // this function doesn't match
    561                                                                         throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
     506                                                                        throw SemanticError( function, "candidate function not viable: too many mutex arguments\n" );
    562507                                                                }
    563508
     
    571516                                                                        (*param)->get_type()->print( ss );
    572517                                                                        ss << "'\n";
    573                                                                         throw SemanticError(ss.str(), function);
     518                                                                        throw SemanticError( function, ss.str() );
    574519                                                                }
    575520
     
    583528                                                                // We ran out of arguments but still have parameters left
    584529                                                                // this function doesn't match
    585                                                                 throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
     530                                                                throw SemanticError( function, "candidate function not viable: too few mutex arguments\n" );
    586531                                                        }
    587532
     
    610555
    611556                        // Make sure we got the right number of arguments
    612                         if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
    613                         if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
    614                         if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
    615                         if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
    616                         // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
     557                        if( func_candidates.empty() )    { SemanticError top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
     558                        if( args_candidates.empty() )    { SemanticError top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
     559                        if( func_candidates.size() > 1 ) { SemanticError top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
     560                        if( args_candidates.size() > 1 ) { SemanticError top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
     561
    617562
    618563                        // Swap the results from the alternative with the unresolved values.
     
    647592        }
    648593
    649         bool isStructOrUnion( const Alternative & alt ) {
    650                 Type * t = alt.expr->result->stripReferences();
     594        bool isStructOrUnion( Type * t ) {
     595                t = t->stripReferences();
    651596                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    652597        }
Note: See TracChangeset for help on using the changeset viewer.