Changes in src/ResolvExpr/Resolver.cc [c71b256:d55d7a6]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
rc71b256 rd55d7a6 105 105 } 106 106 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 ); 125 111 } 126 112 … … 144 130 } // namespace 145 131 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 0154 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 } // for161 } // if162 #endif163 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 remaining172 // choose the lowest cost expression among the candidates173 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 statement187 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 messages195 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 expressions208 return true;209 }210 } // namespace211 212 // used in resolveTypeof213 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 0220 // interpretations, an exception has already been thrown.221 assertf( expr, "expected a non-null expression." );222 223 static CastExpr untyped( nullptr ); // cast to void224 225 // set up and resolve expression cast to void226 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 expression233 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 program237 untyped.arg = nullptr;238 return ret;239 }240 241 132 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 242 133 resetTyVarRenaming(); 243 134 TypeEnvironment env; 244 Expression * 135 Expression *newExpr = resolveInVoidContext( untyped, indexer, env ); 245 136 finishExpr( newExpr, env, untyped->env ); 246 137 delete untyped; … … 249 140 250 141 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; 252 162 } 253 163 … … 260 170 261 171 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 ) { 264 209 if ( dynamic_cast< EnumInstType * >( type ) ) { 265 210 return true; … … 484 429 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name; 485 430 ss << "' in call to waitfor"; 486 throw SemanticError( s s.str() );431 throw SemanticError( stmt->location, ss.str() ); 487 432 } 488 433 … … 506 451 PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() ); 507 452 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" ); 509 454 } 510 455 511 456 FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() ); 512 457 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" ); 514 459 } 515 460 … … 520 465 521 466 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"); 523 468 } 524 469 } … … 559 504 // We ran out of parameters but still have arguments 560 505 // 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" ); 562 507 } 563 508 … … 571 516 (*param)->get_type()->print( ss ); 572 517 ss << "'\n"; 573 throw SemanticError( ss.str(), function);518 throw SemanticError( function, ss.str() ); 574 519 } 575 520 … … 583 528 // We ran out of arguments but still have parameters left 584 529 // 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" ); 586 531 } 587 532 … … 610 555 611 556 // 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 617 562 618 563 // Swap the results from the alternative with the unresolved values. … … 647 592 } 648 593 649 bool isStructOrUnion( const Alternative & alt ) {650 Type * t = alt.expr->result->stripReferences();594 bool isStructOrUnion( Type * t ) { 595 t = t->stripReferences(); 651 596 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ); 652 597 }
Note:
See TracChangeset
for help on using the changeset viewer.