Ignore:
Timestamp:
Jun 11, 2019, 1:36:00 PM (5 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
3da7c19
Parents:
396037d
Message:

More resolver porting

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    r396037d rd57e349  
    1717
    1818#include <sstream>
     19#include <string>
     20#include <unordered_map>
    1921
    2022#include "Candidate.hpp"
    2123#include "CompilationState.h"
     24#include "Cost.h"
     25#include "Resolver.h"
    2226#include "SatisfyAssertions.hpp"
     27#include "typeops.h"              // for adjustExprType
    2328#include "AST/Expr.hpp"
    2429#include "AST/Node.hpp"
    2530#include "AST/Pass.hpp"
     31#include "AST/Print.hpp"
     32#include "SymTab/Mangler.h"
    2633
    2734#define PRINT( text ) if ( resolvep ) { text }
     
    4956        /// return type. Skips ambiguous candidates.
    5057        CandidateList pruneCandidates( CandidateList & candidates ) {
    51                 #warning unimplemented
    52                 (void)candidates;
    53                 assert(false);
    54                 return {};
     58                struct PruneStruct {
     59                        CandidateRef candidate;
     60                        bool ambiguous;
     61
     62                        PruneStruct() = default;
     63                        PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
     64                };
     65
     66                // find lowest-cost candidate for each type
     67                std::unordered_map< std::string, PruneStruct > selected;
     68                for ( CandidateRef & candidate : candidates ) {
     69                        std::string mangleName;
     70                        {
     71                                ast::ptr< ast::Type > newType = candidate->expr->result;
     72                                candidate->env.apply( newType );
     73                                mangleName = Mangle::mangle( newType );
     74                        }
     75
     76                        auto found = selected.find( mangleName );
     77                        if ( found != selected.end() ) {
     78                                if ( candidate->cost < found->second.candidate->cost ) {
     79                                        PRINT(
     80                                                std::cerr << "cost " << candidate->cost << " beats "
     81                                                        << found->second.candidate->cost << std::endl;
     82                                        )
     83
     84                                        found->second = PruneStruct{ candidate };
     85                                } else if ( candidate->cost == found->second.candidate->cost ) {
     86                                        // if one of the candidates contains a deleted identifier, can pick the other,
     87                                        // since deleted expressions should not be ambiguous if there is another option
     88                                        // that is at least as good
     89                                        if ( findDeletedExpr( candidate->expr ) ) {
     90                                                // do nothing
     91                                                PRINT( std::cerr << "candidate is deleted" << std::endl; )
     92                                        } else if ( findDeletedExpr( found->second.candidate->expr ) ) {
     93                                                PRINT( std::cerr << "current is deleted" << std::endl; )
     94                                                found->second = PruneStruct{ candidate };
     95                                        } else {
     96                                                PRINT( std::cerr << "marking ambiguous" << std::endl; )
     97                                                found->second.ambiguous = true;
     98                                        }
     99                                } else {
     100                                        PRINT(
     101                                                std::cerr << "cost " << candidate->cost << " loses to "
     102                                                        << found->second.candidate->cost << std::endl;
     103                                        )
     104                                }
     105                        } else {
     106                                selected.emplace_hint( found, mangleName, candidate );
     107                        }
     108                }
     109
     110                // report unambiguous min-cost candidates
     111                CandidateList out;
     112                for ( auto & target : selected ) {
     113                        if ( target.second.ambiguous ) continue;
     114
     115                        CandidateRef cand = target.second.candidate;
     116                       
     117                        ast::ptr< ast::Type > newResult = cand->expr->result;
     118                        cand->env.applyFree( newResult );
     119                        cand->expr = ast::mutate_field(
     120                                cand->expr.get(), &ast::Expr::result, std::move( newResult ) );
     121                       
     122                        out.emplace_back( cand );
     123                }
     124                return out;
     125        }
     126
     127        /// Returns a list of alternatives with the minimum cost in the given list
     128        CandidateList findMinCost( const CandidateList & candidates ) {
     129                CandidateList out;
     130                Cost minCost = Cost::infinity;
     131                for ( const CandidateRef & r : candidates ) {
     132                        if ( r->cost < minCost ) {
     133                                minCost = r->cost;
     134                                out.clear();
     135                                out.emplace_back( r );
     136                        } else if ( r->cost == minCost ) {
     137                                out.emplace_back( r );
     138                        }
     139                }
     140                return out;
    55141        }
    56142
     
    91177        if ( mode.prune ) {
    92178                // trim candidates to single best one
    93                 auto oldsize = candidates.size();
    94179                PRINT(
    95180                        std::cerr << "alternatives before prune:" << std::endl;
     
    98183
    99184                CandidateList pruned = pruneCandidates( candidates );
     185               
    100186                if ( mode.failFast && pruned.empty() ) {
    101187                        std::ostringstream stream;
    102                         CandidateList winners;
    103                        
    104                         #warning unimplemented
    105                         assert(false);
    106                 }
    107         }
    108 
    109         #warning unimplemented
    110         assert(false);
     188                        CandidateList winners = findMinCost( candidates );
     189                        stream << "Cannot choose between " << winners.size() << " alternatives for "
     190                                "expression\n";
     191                        ast::print( stream, expr );
     192                        stream << " Alternatives are:\n";
     193                        print( stream, winners, 1 );
     194                        SemanticError( expr->location, stream.str() );
     195                }
     196
     197                auto oldsize = candidates.size();
     198                candidates = std::move( pruned );
     199
     200                PRINT(
     201                        std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;
     202                )
     203                PRINT(
     204                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
     205                                << std::endl;
     206                )
     207        }
     208
     209        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
     210        // adjusted
     211        if ( mode.adjust ) {
     212                for ( CandidateRef & r : candidates ) {
     213                        r->expr = ast::mutate_field(
     214                                r->expr.get(), &ast::Expr::result,
     215                                adjustExprType( r->expr->result, r->env, symtab ) );
     216                }
     217        }
     218
     219        // Central location to handle gcc extension keyword, etc. for all expressions
     220        for ( CandidateRef & r : candidates ) {
     221                if ( r->expr->extension != expr->extension ) {
     222                        r->expr.get_and_mutate()->extension = expr->extension;
     223                }
     224        }
    111225}
    112226
Note: See TracChangeset for help on using the changeset viewer.