- File:
-
- 1 edited
-
src/ResolvExpr/CandidateFinder.cpp (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
r85855b0 r0f5e8cd 513 513 // add new result 514 514 assert( common ); 515 516 auto paramAsEnum = dynamic_cast<const ast::EnumInstType *>(paramType); 517 auto argAsEnum =dynamic_cast<const ast::EnumInstType *>(argType); 518 if (paramAsEnum && argAsEnum) { 519 if (paramAsEnum->base->name != argAsEnum->base->name) { 520 Cost c = castCost(argType, paramType, expr, context.symtab, env); 521 if (c < Cost::infinity) { 522 CandidateFinder subFinder( context, env ); 523 expr = subFinder.makeEnumOffsetCast(argAsEnum, paramAsEnum, expr, c); 524 results.emplace_back( 525 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 526 nextArg + 1, nTuples, expl.cost + c, expl.exprs.size() == 1 ? 0 : 1, j ); 527 continue; 528 } else { 529 std::cerr << "Cannot instantiate " << paramAsEnum->base->name << " with " << argAsEnum->base->name << std::endl; 530 } 531 } 532 } 533 results.emplace_back( 534 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 535 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 515 results.emplace_back( 516 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 517 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 518 //} 536 519 } 537 520 } … … 649 632 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 650 633 const Candidate & cand, const Cost & addedCost, const std::string & name 651 );652 653 void addEnumValueAsCandidate(const ast::EnumInstType * instType, const ast::Expr * expr,654 const Cost & addedCost655 634 ); 656 635 … … 697 676 void postvisit( const ast::QualifiedNameExpr * qualifiedExpr ); 698 677 699 const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src,700 const ast::EnumInstType * dst701 , const ast::Expr * expr, Cost minCost );702 703 678 void postvisit( const ast::InitExpr * ) { 704 679 assertf( false, "CandidateFinder should never see a resolved InitExpr." ); … … 901 876 } 902 877 903 void Finder::addEnumValueAsCandidate( const ast::EnumInstType * enumInst, const ast::Expr * expr,904 const Cost & addedCost905 ) {906 if ( enumInst->base->base ) {907 CandidateFinder finder( context, tenv );908 auto location = expr->location;909 auto callExpr = new ast::UntypedExpr(910 location, new ast::NameExpr( location, "valueE" ), {expr}911 );912 finder.find( callExpr );913 CandidateList winners = findMinCost( finder.candidates );914 if (winners.size() != 1) {915 SemanticError( callExpr, "Ambiguous expression in valueE..." );916 }917 CandidateRef & choice = winners.front();918 choice->cost += addedCost;919 addAnonConversions(choice);920 candidates.emplace_back( std::move(choice) );921 }922 }923 924 878 /// Adds implicit struct-conversions to the alternative list 925 879 void Finder::addAnonConversions( const CandidateRef & cand ) { … … 940 894 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 941 895 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 942 addEnumValueAsCandidate(enumInst, aggrExpr, Cost::unsafe); 943 } 944 } 945 896 if ( enumInst->base->base ) { 897 CandidateFinder finder( context, tenv ); 898 auto location = aggrExpr->location; 899 auto callExpr = new ast::UntypedExpr( 900 location, new ast::NameExpr( location, "valueE" ), {aggrExpr} 901 ); 902 finder.find( callExpr ); 903 CandidateList winners = findMinCost( finder.candidates ); 904 if (winners.size() != 1) { 905 SemanticError( callExpr, "Ambiguous expression in valueE..." ); 906 } 907 CandidateRef & choice = winners.front(); 908 choice->cost = Cost::unsafe; 909 candidates.emplace_back( std::move(choice) ); 910 } 911 912 } 913 } 946 914 947 915 /// Adds aggregate member interpretations … … 1212 1180 } 1213 1181 1214 // src is a subset of dst1215 const ast::Expr * Finder::makeEnumOffsetCast( const ast::EnumInstType * src,1216 const ast::EnumInstType * dst,1217 const ast::Expr * expr,1218 Cost minCost ) {1219 1220 auto srcDecl = src->base;1221 auto dstDecl = dst->base;1222 1223 if (srcDecl->name == dstDecl->name) return expr;1224 1225 for (auto& dstChild: dstDecl->inlinedDecl) {1226 Cost c = castCost(src, dstChild, false, symtab, tenv);1227 ast::CastExpr * castToDst;1228 if (c<minCost) {1229 unsigned offset = dstDecl->calChildOffset(dstChild.get());1230 if (offset > 0) {1231 auto untyped = ast::UntypedExpr::createCall(1232 expr->location,1233 "?+?",1234 { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ),1235 ast::ConstantExpr::from_int(expr->location, offset)});1236 CandidateFinder finder(context, tenv);1237 finder.find( untyped );1238 CandidateList winners = findMinCost( finder.candidates );1239 CandidateRef & choice = winners.front();1240 // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );1241 choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast);1242 // castToDst = new ast::CastExpr(choice->expr, dstChild);1243 castToDst = new ast::CastExpr(1244 makeEnumOffsetCast( src, dstChild, choice->expr, minCost ),1245 dst);1246 1247 } else {1248 castToDst = new ast::CastExpr( expr, dst );1249 }1250 return castToDst;1251 }1252 }1253 SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name);1254 return nullptr;1255 }1256 1257 1182 void Finder::postvisit( const ast::CastExpr * castExpr ) { 1258 1183 ast::ptr< ast::Type > toType = castExpr->result; … … 1304 1229 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ) 1305 1230 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ); 1306 1307 // Redefine enum cast1308 auto argAsEnum = cand->expr->result.as<ast::EnumInstType>();1309 auto toAsEnum = toType.as<ast::EnumInstType>();1310 if ( argAsEnum && toAsEnum && argAsEnum->name != toAsEnum->name ) {1311 ast::ptr<ast::Expr> offsetExpr = makeEnumOffsetCast(argAsEnum, toAsEnum, cand->expr, thisCost);1312 cand->expr = offsetExpr;1313 }1314 1231 1315 1232 PRINT( … … 1329 1246 minCastCost = thisCost; 1330 1247 matches.clear(); 1331 } 1332 // ambigious case, still output candidates to print in error message 1248 1249 1250 } 1251 // ambiguous case, still output candidates to print in error message 1333 1252 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1334 1253 CandidateRef newCand = std::make_shared<Candidate>( … … 1345 1264 } 1346 1265 candidates = std::move(matches); 1266 1347 1267 //CandidateList minArgCost = findMinCost( matches ); 1348 1268 //promoteCvtCost( minArgCost ); … … 1454 1374 } 1455 1375 } else { 1456 declList = symtab.lookupId IgnoreHidden( nameExpr->name );1376 declList = symtab.lookupId( nameExpr->name ); 1457 1377 } 1458 1378 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) … … 1466 1386 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1467 1387 1388 // bool bentConversion = false; 1389 // if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) { 1390 // if ( inst->base && inst->base->base ) { 1391 // bentConversion = true; 1392 // } 1393 // } 1394 1395 // CandidateRef newCand = std::make_shared<Candidate>( 1396 // newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero, 1397 // cost ); 1468 1398 CandidateRef newCand = std::make_shared<Candidate>( 1469 1399 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, … … 1883 1813 if ( const ast::EnumInstType * enumInstType = 1884 1814 dynamic_cast<const ast::EnumInstType *>( t ) ) { 1885 if ( (enumInstType->base->name == expr->type_name) 1886 || (expr->type_decl && enumInstType->base->name == expr->type_decl->name) ) { 1815 if ( enumInstType->base->name == expr->type_decl->name ) { 1887 1816 Cost cost = Cost::zero; 1888 1817 ast::Expr * newExpr = data.combine( expr->location, cost ); 1818 // CandidateRef newCand = 1819 // std::make_shared<Candidate>( 1820 // newExpr, copy( tenv ), ast::OpenVarSet{}, 1821 // ast::AssertionSet{}, Cost::safe, cost 1822 // ); 1889 1823 CandidateRef newCand = 1890 1824 std::make_shared<Candidate>( … … 2162 2096 2163 2097 return expr; 2164 }2165 2166 const ast::Expr * CandidateFinder::makeEnumOffsetCast( const ast::EnumInstType * src,2167 const ast::EnumInstType * dst,2168 const ast::Expr * expr,2169 Cost minCost ) {2170 2171 auto srcDecl = src->base;2172 auto dstDecl = dst->base;2173 2174 if (srcDecl->name == dstDecl->name) return expr;2175 2176 for (auto& dstChild: dstDecl->inlinedDecl) {2177 Cost c = castCost(src, dstChild, false, context.symtab, env);2178 ast::CastExpr * castToDst;2179 if (c<minCost) {2180 unsigned offset = dstDecl->calChildOffset(dstChild.get());2181 if (offset > 0) {2182 auto untyped = ast::UntypedExpr::createCall(2183 expr->location,2184 "?+?",2185 { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ),2186 ast::ConstantExpr::from_int(expr->location, offset)});2187 CandidateFinder finder(context, env);2188 finder.find( untyped );2189 CandidateList winners = findMinCost( finder.candidates );2190 CandidateRef & choice = winners.front();2191 choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast);2192 castToDst = new ast::CastExpr(2193 makeEnumOffsetCast( src, dstChild, choice->expr, minCost ),2194 dst);2195 } else {2196 castToDst = new ast::CastExpr( expr, dst );2197 }2198 return castToDst;2199 }2200 }2201 SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name);2202 return nullptr;2203 2098 } 2204 2099
Note:
See TracChangeset
for help on using the changeset viewer.