Changeset 8587878e


Ignore:
Timestamp:
Jan 5, 2018, 4:44:34 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
94e025a2
Parents:
a974dad
Message:

Refactor findIntegralExpression and use it to resolve if/for/while conditions [fixes #76]

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    ra974dad r8587878e  
    171171
    172172        namespace {
     173                /// resolve `untyped` to the expression whose type satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
     174                template<typename Pred>
     175                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, Pred pred) {
     176                        TypeEnvironment env;
     177                        AlternativeFinder finder( indexer, env );
     178                        finder.findWithAdjustment( untyped );
     179
     180                        AltList candidates;
     181                        for ( Alternative & alt : finder.get_alternatives() ) {
     182                                if ( pred( alt.expr->result ) ) {
     183                                        candidates.push_back( std::move( alt ) );
     184                                }
     185                        }
     186
     187                        // choose the lowest cost expression among the candidates
     188                        AltList winners;
     189                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     190                        if ( winners.size() == 0 ) {
     191                                throw SemanticError( "No reasonable alternatives for " + kindStr + " expression: ", untyped );
     192                        } else if ( winners.size() != 1 ) {
     193                                std::ostringstream stream;
     194                                stream << "Cannot choose between " << winners.size() << " alternatives for " + kindStr +  " expression\n";
     195                                untyped->print( stream );
     196                                stream << "Alternatives are:\n";
     197                                printAlts( winners, stream, 1 );
     198                                throw SemanticError( stream.str() );
     199                        }
     200
     201                        // there is one unambiguous interpretation - move the expression into the with statement
     202                        Alternative & alt = winners.front();
     203                        finishExpr( alt.expr, alt.env, untyped->env );
     204                        delete untyped;
     205                        untyped = alt.expr;
     206                        alt.expr = nullptr;
     207                }
     208
    173209                bool isIntegralType( Type *type ) {
    174210                        if ( dynamic_cast< EnumInstType * >( type ) ) {
     
    184220
    185221                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    186                         TypeEnvironment env;
    187                         AlternativeFinder finder( indexer, env );
    188                         finder.find( untyped );
    189 #if 0
    190                         if ( finder.get_alternatives().size() != 1 ) {
    191                                 std::cout << "untyped expr is ";
    192                                 untyped->print( std::cout );
    193                                 std::cout << std::endl << "alternatives are:";
    194                                 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    195                                         i->print( std::cout );
    196                                 } // for
    197                         } // if
    198 #endif
    199                         Expression *newExpr = 0;
    200                         const TypeEnvironment *newEnv = 0;
    201                         for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    202                                 if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) {
    203                                         if ( newExpr ) {
    204                                                 throw SemanticError( "Too many interpretations for case control expression", untyped );
    205                                         } else {
    206                                                 newExpr = i->expr->clone();
    207                                                 newEnv = &i->env;
    208                                         } // if
    209                                 } // if
    210                         } // for
    211                         if ( ! newExpr ) {
    212                                 throw SemanticError( "No interpretations for case control expression", untyped );
    213                         } // if
    214                         finishExpr( newExpr, *newEnv, untyped->env );
    215                         delete untyped;
    216                         untyped = newExpr;
    217                 }
    218 
     222                        findKindExpression( untyped, indexer, "condition", isIntegralType );
     223                }
    219224        }
    220225
     
    311316
    312317        void Resolver::previsit( IfStmt *ifStmt ) {
    313                 findSingleExpression( ifStmt->condition, indexer );
     318                findIntegralExpression( ifStmt->condition, indexer );
    314319        }
    315320
    316321        void Resolver::previsit( WhileStmt *whileStmt ) {
    317                 findSingleExpression( whileStmt->condition, indexer );
     322                findIntegralExpression( whileStmt->condition, indexer );
    318323        }
    319324
    320325        void Resolver::previsit( ForStmt *forStmt ) {
    321326                if ( forStmt->condition ) {
    322                         findSingleExpression( forStmt->condition, indexer );
     327                        findIntegralExpression( forStmt->condition, indexer );
    323328                } // if
    324329
     
    579584        }
    580585
     586
    581587        void Resolver::previsit( WithStmt * withStmt ) {
    582588                for ( Expression *& expr : withStmt->exprs )  {
    583                         TypeEnvironment env;
    584                         AlternativeFinder finder( indexer, env );
    585                         finder.findWithAdjustment( expr );
    586 
    587589                        // only struct- and union-typed expressions are viable candidates
    588                         AltList candidates;
    589                         for ( Alternative & alt : finder.get_alternatives() ) {
    590                                 if ( isStructOrUnion( alt.expr->result ) ) {
    591                                         candidates.push_back( std::move( alt ) );
    592                                 }
    593                         }
    594 
    595                         // choose the lowest cost expression among the candidates
    596                         AltList winners;
    597                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    598                         if ( winners.size() == 0 ) {
    599                                 throw SemanticError( "No reasonable alternatives for with statement expression: ", expr );
    600                         } else if ( winners.size() != 1 ) {
    601                                 std::ostringstream stream;
    602                                 stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n";
    603                                 expr->print( stream );
    604                                 stream << "Alternatives are:\n";
    605                                 printAlts( winners, stream, 1 );
    606                                 throw SemanticError( stream.str() );
    607                         }
    608 
    609                         // there is one unambiguous interpretation - move the expression into the with statement
    610                         Alternative & alt = winners.front();
    611                         finishExpr( alt.expr, alt.env, expr->env );
    612                         delete expr;
    613                         expr = alt.expr;
    614                         alt.expr = nullptr;
     590                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
    615591
    616592                        // if with expression might be impure, create a temporary so that it is evaluated once
Note: See TracChangeset for help on using the changeset viewer.