Changeset d57e349 for src/ResolvExpr/CandidateFinder.cpp
- Timestamp:
- Jun 11, 2019, 1:36:00 PM (5 years ago)
- 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
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
r396037d rd57e349 17 17 18 18 #include <sstream> 19 #include <string> 20 #include <unordered_map> 19 21 20 22 #include "Candidate.hpp" 21 23 #include "CompilationState.h" 24 #include "Cost.h" 25 #include "Resolver.h" 22 26 #include "SatisfyAssertions.hpp" 27 #include "typeops.h" // for adjustExprType 23 28 #include "AST/Expr.hpp" 24 29 #include "AST/Node.hpp" 25 30 #include "AST/Pass.hpp" 31 #include "AST/Print.hpp" 32 #include "SymTab/Mangler.h" 26 33 27 34 #define PRINT( text ) if ( resolvep ) { text } … … 49 56 /// return type. Skips ambiguous candidates. 50 57 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; 55 141 } 56 142 … … 91 177 if ( mode.prune ) { 92 178 // trim candidates to single best one 93 auto oldsize = candidates.size();94 179 PRINT( 95 180 std::cerr << "alternatives before prune:" << std::endl; … … 98 183 99 184 CandidateList pruned = pruneCandidates( candidates ); 185 100 186 if ( mode.failFast && pruned.empty() ) { 101 187 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 } 111 225 } 112 226
Note: See TracChangeset
for help on using the changeset viewer.