Changeset af746cc for src/ResolvExpr
- Timestamp:
- Apr 15, 2024, 12:03:53 PM (8 months ago)
- Branches:
- master
- Children:
- dc58e5d
- Parents:
- d9bad51
- Location:
- src/ResolvExpr
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
rd9bad51 raf746cc 285 285 const CodeLocation & location, 286 286 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args, 287 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,287 std::vector< ArgPack > & results, std::size_t & genStart, const ResolveContext & context, 288 288 unsigned nTuples = 0 289 289 ) { … … 295 295 // ^^^ need to handle the case where a tuple has a default argument 296 296 if ( ! instantiateArgument( location, 297 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;297 type, nullptr, args, results, genStart, context, nTuples ) ) return false; 298 298 nTuples = 0; 299 299 } … … 510 510 511 511 // attempt to unify types 512 if ( unify( paramType, argType, env, need, have, open ) ) { 512 ast::ptr<ast::Type> common; 513 if ( unify( paramType, argType, env, need, have, open, common ) ) { 513 514 // add new result 514 results.emplace_back( 515 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 516 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 515 assert( common ); 516 // auto attrType = common.as<ast::EnumAttrType>(); 517 // if ( attrType && ( attrType->attr == ast::EnumAttribute::Value ) ) { 518 // auto callExpr = new ast::UntypedExpr( 519 // expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 520 // CandidateFinder finder( context, env ); 521 // finder.find( callExpr ); 522 // CandidateList winners = findMinCost( finder.candidates ); 523 // if (winners.size() != 1) { 524 // SemanticError( callExpr, "Ambiguous expression in valueE" ); 525 // } 526 // CandidateRef & choice = winners.front(); 527 // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 528 529 // results.emplace_back( 530 // i, choice->expr, 531 // std::move( env ), std::move( need ), std::move( have ), std::move( open ), 532 // nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 533 // } else { 534 results.emplace_back( 535 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 536 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 537 //} 517 538 } 518 539 } … … 786 807 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 787 808 if ( !instantiateArgument( location, 788 funcType->params[i], obj->init, args, results, genStart, symtab)) return;809 funcType->params[i], obj->init, args, results, genStart, context)) return; 789 810 } 790 811 goto endMatch; … … 796 817 // no default args for indirect calls 797 818 if ( !instantiateArgument( location, 798 param, nullptr, args, results, genStart, symtab) ) return;819 param, nullptr, args, results, genStart, context ) ) return; 799 820 } 800 821 … … 891 912 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 892 913 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 893 } 894 else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 895 if (enumInst->base && enumInst->base->base) { 896 const CodeLocation &location = cand->expr->location; 897 898 CandidateFinder funcFinder(context, tenv); 899 auto nameExpr = new ast::NameExpr(location, "valueE"); 900 ResolveMode mode = {true, false, selfFinder.candidates.empty()}; 901 funcFinder.find( nameExpr, mode ); 902 903 // make variableExpr itself the candidate for the value Call 904 ExplodedArgs argExpansions; 905 argExpansions.emplace_back(); 906 auto &argE = argExpansions.back(); 907 908 argE.emplace_back(*cand, symtab); // Use the typed name expr as param for value 909 910 CandidateList found; 911 SemanticErrorException errors; 912 913 for (CandidateRef &func : funcFinder) { 914 try { 915 const ast::Type *funcResult = 916 func->expr->result->stripReferences(); 917 if (auto pointer = dynamic_cast<const ast::PointerType *>( 918 funcResult)) { 919 if (auto function = 920 pointer->base.as<ast::FunctionType>()) { 921 CandidateRef newFunc{new Candidate{*func}}; 922 newFunc->expr = referenceToRvalueConversion( 923 newFunc->expr, newFunc->cost); 924 makeFunctionCandidates( location, 925 newFunc, function, 926 argExpansions, found ); 927 } 928 } 929 } catch (SemanticErrorException &e) { 930 std::cerr 931 << "Resolving value function should cause an error" 932 << std::endl; 933 errors.append(e); 934 } 935 } 936 937 if (found.empty()) { 938 std::cerr << "Resolve value function should always success" 939 << std::endl; 940 } 941 942 for (CandidateRef &withFunc : found) { 943 withFunc->cost.incSafe(); 944 Cost cvtCost = 945 computeApplicationConversionCost(withFunc, symtab); 946 assert(cvtCost != Cost::infinity); 947 948 candidates.emplace_back(std::move(withFunc)); 949 } 950 } 914 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 915 if ( enumInst->base->base ) { 916 CandidateFinder finder( context, tenv ); 917 auto location = aggrExpr->location; 918 auto callExpr = new ast::UntypedExpr( 919 location, new ast::NameExpr( location, "valueE" ), {aggrExpr} 920 ); 921 finder.find( callExpr ); 922 CandidateList winners = findMinCost( finder.candidates ); 923 if (winners.size() != 1) { 924 SemanticError( callExpr, "Ambiguous expression in valueE" ); 925 } 926 CandidateRef & choice = winners.front(); 927 // choice->cost.incSafe(); 928 candidates.emplace_back( std::move(choice) ); 929 } 930 951 931 } 952 932 } … … 1415 1395 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1416 1396 1397 bool bentConversion = false; 1398 if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) { 1399 if ( inst->base && inst->base->base ) { 1400 bentConversion = true; 1401 } 1402 } 1403 1417 1404 CandidateRef newCand = std::make_shared<Candidate>( 1418 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,1405 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero, 1419 1406 cost ); 1420 1407 … … 1449 1436 auto cand = new Candidate(variableExpr, tenv); 1450 1437 candidates.emplace_back(cand); 1451 1452 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(1453 variableExpr->var->get_type())) {1454 if (enumInst->base && enumInst->base->base) {1455 const CodeLocation &location = cand->expr->location;1456 1457 CandidateFinder funcFinder(context, tenv);1458 auto nameExpr = new ast::NameExpr(location, "valueE");1459 ResolveMode mode = {true, false, selfFinder.candidates.empty()};1460 funcFinder.find( nameExpr, mode );1461 1462 // make variableExpr itself the candidate for the value Call1463 ExplodedArgs argExpansions;1464 argExpansions.emplace_back();1465 auto &argE = argExpansions.back();1466 1467 argE.emplace_back(*cand, symtab);1468 1469 CandidateList found;1470 SemanticErrorException errors;1471 1472 for (CandidateRef &func : funcFinder) {1473 try {1474 const ast::Type *funcResult =1475 func->expr->result->stripReferences();1476 if (auto pointer = dynamic_cast<const ast::PointerType *>(1477 funcResult)) {1478 if (auto function =1479 pointer->base.as<ast::FunctionType>()) {1480 CandidateRef newFunc{new Candidate{*func}};1481 newFunc->expr = referenceToRvalueConversion(1482 newFunc->expr, newFunc->cost);1483 makeFunctionCandidates(variableExpr->location,1484 newFunc, function,1485 argExpansions, found);1486 }1487 }1488 } catch (SemanticErrorException &e) {1489 std::cerr1490 << "Resolving value function should cause an error"1491 << std::endl;1492 errors.append(e);1493 }1494 }1495 1496 if (found.empty()) {1497 std::cerr << "Resolve value function should always success"1498 << std::endl;1499 }1500 1501 for (CandidateRef &withFunc : found) {1502 withFunc->cost.incSafe();1503 Cost cvtCost =1504 computeApplicationConversionCost(withFunc, symtab);1505 assert(cvtCost != Cost::infinity);1506 1507 candidates.emplace_back(std::move(withFunc));1508 }1509 }1510 }1511 1438 } 1512 1439 … … 1840 1767 1841 1768 // unification run for side-effects 1842 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1769 ast::ptr<ast::Type> common; 1770 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, common ); 1843 1771 (void) canUnify; 1844 1772 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), … … 1865 1793 // ambiguous case, still output candidates to print in error message 1866 1794 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1867 CandidateRef newCand = std::make_shared<Candidate>( 1868 new ast::InitExpr{ 1869 initExpr->location, 1870 restructureCast( cand->expr, toType ), 1871 initAlt.designation }, 1872 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1873 // currently assertions are always resolved immediately so this should have no effect. 1874 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1875 // we may need to revisit the logic. 1876 inferParameters( newCand, matches ); 1877 } 1878 } 1795 auto commonAsEnumAttr = common.as<ast::EnumAttrType>(); 1796 if ( commonAsEnumAttr && commonAsEnumAttr->attr == ast::EnumAttribute::Value ) { 1797 1798 auto callExpr = new ast::UntypedExpr( 1799 cand->expr->location, new ast::NameExpr( cand->expr->location, "valueE"), {cand->expr} ); 1800 CandidateFinder finder( context, env ); 1801 finder.find( callExpr ); 1802 CandidateList winners = findMinCost( finder.candidates ); 1803 if (winners.size() != 1) { 1804 SemanticError( callExpr, "Ambiguous expression in valueE" ); 1805 } 1806 CandidateRef & choice = winners.front(); 1807 // assert( valueCall->result ); 1808 CandidateRef newCand = std::make_shared<Candidate>( 1809 new ast::InitExpr{ 1810 initExpr->location, 1811 // restructureCast( cand->expr, toType ), 1812 choice->expr, 1813 initAlt.designation }, 1814 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1815 inferParameters( newCand, matches ); 1816 } else { 1817 CandidateRef newCand = std::make_shared<Candidate>( 1818 new ast::InitExpr{ 1819 initExpr->location, 1820 restructureCast( cand->expr, toType ), 1821 initAlt.designation }, 1822 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1823 // currently assertions are always resolved immediately so this should have no effect. 1824 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1825 // we may need to revisit the logic. 1826 inferParameters( newCand, matches ); 1827 } 1828 } 1829 } 1879 1830 } 1880 1831 } … … 1901 1852 std::make_shared<Candidate>( 1902 1853 newExpr, copy( tenv ), ast::OpenVarSet{}, 1903 ast::AssertionSet{}, Cost:: zero, cost1854 ast::AssertionSet{}, Cost::safe, cost 1904 1855 ); 1905 1856 … … 2201 2152 } 2202 2153 2154 // get the valueE(...) ApplicationExpr that returns the enum value 2155 const ast::Expr * getValueEnumCall( 2156 const ast::Expr * expr, 2157 const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env ) { 2158 auto callExpr = new ast::UntypedExpr( 2159 expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 2160 CandidateFinder finder( context, env ); 2161 finder.find( callExpr ); 2162 CandidateList winners = findMinCost( finder.candidates ); 2163 if (winners.size() != 1) { 2164 SemanticError( callExpr, "Ambiguous expression in valueE" ); 2165 } 2166 CandidateRef & choice = winners.front(); 2167 return choice->expr; 2168 // return std::move( choice->expr.get() ); 2169 } 2170 2203 2171 } // namespace ResolvExpr 2204 2172 -
src/ResolvExpr/CandidateFinder.hpp
rd9bad51 raf746cc 70 70 const ast::Expr * expr, Cost & cost ); 71 71 72 const ast::Expr * getValueEnumCall(const ast::Expr * expr, 73 const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env ); 74 72 75 } // namespace ResolvExpr 73 76 -
src/ResolvExpr/CommonType.cc
rd9bad51 raf746cc 385 385 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 386 386 const ast::EnumDecl* enumDecl = enumInst->base; 387 if ( enumDecl->base ) { 388 result = enumDecl->base.get(); 389 } else { 387 if ( !enumDecl->base ) { 390 388 ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ]; 391 389 if ( … … 398 396 } 399 397 } 400 } else if ( dynamic_cast< const ast::EnumPosType * >( type2 ) ) { 401 ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ]; 402 if ( 403 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 404 || widen.first ) 405 && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 406 || widen.second ) 407 ) { 408 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 409 } 398 } else if ( auto type2AsAttr = dynamic_cast< const ast::EnumAttrType * >( type2 ) ) { 399 if ( type2AsAttr->attr == ast::EnumAttribute::Posn ) { 400 ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ]; 401 if ( 402 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 403 || widen.first ) 404 && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 405 || widen.second ) 406 ) { 407 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 408 } 409 } 410 410 } 411 411 } … … 426 426 result = voidPtr; 427 427 add_qualifiers( result, oPtr->qualifiers ); 428 }429 430 // For a typed enum, we want to unify type1 with the base type of the enum431 bool tryResolveWithTypedEnum( const ast::Type * type1 ) {432 if (auto enumInst = dynamic_cast<const ast::EnumInstType *> (type2) ) {433 ast::OpenVarSet newOpen{ open };434 if (enumInst->base->base435 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) {436 result = type1;437 return true;438 }439 }440 return false;441 428 } 442 429 … … 607 594 result = pointer; 608 595 add_qualifiers( result, type2->qualifiers ); 609 } else { 610 tryResolveWithTypedEnum( pointer ); 611 } 612 } 613 614 void postvisit( const ast::ArrayType * arr ) { 615 // xxx - does it make sense? 616 tryResolveWithTypedEnum( arr ); 617 } 596 } 597 } 598 599 void postvisit( const ast::ArrayType * arr ) {} 618 600 619 601 void postvisit( const ast::ReferenceType * ref ) { … … 659 641 } 660 642 661 void postvisit( const ast::FunctionType * func) { 662 tryResolveWithTypedEnum( func ); 663 } 664 665 void postvisit( const ast::StructInstType * inst ) { 666 tryResolveWithTypedEnum( inst ); 667 } 668 669 void postvisit( const ast::UnionInstType * inst ) { 670 tryResolveWithTypedEnum( inst ); 671 } 643 void postvisit( const ast::FunctionType * func) {} 644 645 void postvisit( const ast::StructInstType * inst ) {} 646 647 void postvisit( const ast::UnionInstType * inst ) {} 672 648 673 649 void postvisit( const ast::EnumInstType * enumInst ) { 674 // if ( dynamic_cast<const ast::EnumPosType *>(enumInst) ) { 675 // result = enumInst; 676 // } else 677 if (!dynamic_cast<const ast::EnumInstType *>(type2)) { 678 result = commonType( type2, enumInst, tenv, need, have, open, widen); 679 } 680 } 681 682 void postvisit( const ast::EnumPosType * enumPos ) { 683 if ( auto type2AsPos = dynamic_cast<const ast::EnumPosType *>(type2) ) { 684 // result = commonType( type2AsPos->instance, enumPos->instance, tenv, need, have, open, widen ); 685 // result = enumPos; 686 if ( enumPos->instance->base->name == type2AsPos->instance->base->name ) { 687 result = type2; 688 } 689 } else if ( dynamic_cast<const ast::BasicType *>(type2) ) { 690 result = type2; 691 } 692 } 650 if ( enumInst->base && !enumInst->base->base ) { 651 auto basicType = new ast::BasicType( ast::BasicType::UnsignedInt ); 652 result = commonType( basicType, type2, tenv, need, have, open, widen); 653 } 654 } 655 656 void postvisit( const ast::EnumAttrType * ) {} 693 657 694 658 void postvisit( const ast::TraitInstType * ) {} … … 696 660 void postvisit( const ast::TypeInstType * ) {} 697 661 698 void postvisit( const ast::TupleType * tuple ) { 699 tryResolveWithTypedEnum( tuple ); 700 } 662 void postvisit( const ast::TupleType * tuple ) {} 701 663 702 664 void postvisit( const ast::VarArgsType * ) {} … … 715 677 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 716 678 const ast::EnumDecl * enumDecl = enumInst->base; 717 if ( enumDecl->base ) { 718 if ( tryResolveWithTypedEnum( zero ) ) 719 add_qualifiers( result, zero->qualifiers ); 720 } else { 679 if ( !enumDecl->base ) { 721 680 if ( widen.second || zero->qualifiers <= type2->qualifiers ) { 722 681 result = type2; … … 738 697 ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers }; 739 698 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 740 const ast::EnumDecl * enumBase = enumInst->base; 741 if ( enumBase->base ) { 742 if ( tryResolveWithTypedEnum( one )) 743 add_qualifiers( result, one->qualifiers ); 744 } else { 699 const ast::EnumDecl * enumDecl = enumInst->base; 700 if ( !enumDecl->base ) { 745 701 if ( widen.second || one->qualifiers <= type2->qualifiers ) { 746 702 result = type2; -
src/ResolvExpr/ConversionCost.cc
rd9bad51 raf746cc 278 278 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) { 279 279 conversionCostFromBasicToBasic( basicType, dstAsBasic ); 280 } 281 else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 282 auto enumDecl = enumInst->base; 283 if ( enumDecl->base.get() ) { 284 // cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env ); 285 // cost.incUnsafe(); 286 cost = Cost::infinity; 287 } else { 288 cost = Cost::unsafe; 289 } 290 } else if ( dynamic_cast< const ast::EnumPosType *>(dst) ) { 280 } else if ( dynamic_cast< const ast::EnumAttrType *>(dst) ) { 291 281 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 292 282 cost = costCalc( basicType, integer, srcIsLvalue, symtab, env ); 283 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 284 if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) { 285 cost = Cost::zero; 286 cost.incUnsafe(); 287 } 293 288 } 294 289 } … … 366 361 } 367 362 368 void ConversionCost::postvisit( const ast::EnumInstType * ) { 363 void ConversionCost::postvisit( const ast::EnumInstType * inst ) { 364 if ( inst->base && inst->base->base ) { 365 if ( auto dstAsAttr = dynamic_cast<const ast::EnumAttrType *>( dst ) ) { 366 auto instAsAttr = ast::EnumAttrType( inst, dstAsAttr->attr ); 367 if ( instAsAttr.match(dstAsAttr) ) { 368 cost.incUnsafe(); 369 } 370 371 } else if ( auto dstAsInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 372 if (inst->base && dstAsInst->base) { 373 if (inst->base == dstAsInst->base) { 374 cost.incUnsafe(); 375 } 376 } 377 } else { 378 auto instAsVal = ast::EnumAttrType( inst, ast::EnumAttribute::Value ); 379 cost = costCalc( &instAsVal, dst, srcIsLvalue, symtab, env ); 380 if ( cost < Cost::infinity ) { 381 cost.incUnsafe(); 382 } 383 } 384 return; 385 } 369 386 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 370 387 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); … … 374 391 } 375 392 376 void ConversionCost::postvisit( const ast::EnumPosType * src ) { 377 if ( dynamic_cast<const ast::EnumPosType *>( dst ) ) { 378 // cost = costCalc( src->instance, dstBase->instance, srcIsLvalue, symtab, env ); 379 // if ( cost < Cost::unsafe ) cost.incSafe(); 380 cost = Cost::zero; 381 } else if ( auto dstBase = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 382 cost = costCalc( src->instance, dstBase, srcIsLvalue, symtab, env ); 383 if ( cost < Cost::unsafe ) cost.incSafe(); 384 } else { 385 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 386 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 387 if ( cost < Cost::unsafe ) { 388 cost.incSafe(); 389 } 390 } 391 393 void ConversionCost::postvisit( const ast::EnumAttrType * src ) { 394 auto dstAsEnumAttrType = dynamic_cast<const ast::EnumAttrType *>(dst); 395 if ( src->attr == ast::EnumAttribute::Label ) { 396 if ( dstAsEnumAttrType && dstAsEnumAttrType->attr == ast::EnumAttribute::Label ) { 397 cost = costCalc( src->instance, dstAsEnumAttrType->instance, srcIsLvalue, symtab, env ); 398 } 399 // Add Conversion To String 400 } else if ( src->attr == ast::EnumAttribute::Value ) { 401 if ( dstAsEnumAttrType && dstAsEnumAttrType->attr == ast::EnumAttribute::Value) { 402 cost = costCalc( src->instance, dstAsEnumAttrType->instance, srcIsLvalue, symtab, env ); 403 } else { 404 auto baseType = src->instance->base->base; 405 cost = costCalc( baseType, dst, srcIsLvalue, symtab, env ); 406 if ( cost < Cost::infinity ) { 407 cost.incUnsafe(); 408 } 409 } 410 } else { // ast::EnumAttribute::Posn 411 if ( auto dstBase = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 412 cost = costCalc( src->instance, dstBase, srcIsLvalue, symtab, env ); 413 if ( cost < Cost::unsafe ) cost.incSafe(); 414 } else { 415 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 416 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 417 if ( cost < Cost::unsafe ) { 418 cost.incSafe(); 419 } 420 } 421 } 392 422 } 393 423 … … 466 496 cost.incSafe( maxIntCost + 2 ); 467 497 // assuming 0p is supposed to be used for pointers? 498 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 499 if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) { 500 cost = Cost::zero; 501 cost.incUnsafe(); 502 } 468 503 } 469 504 } … … 483 518 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 484 519 } 520 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 521 if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) { 522 cost = Cost::zero; 523 cost.incUnsafe(); 524 } 485 525 } 486 526 } -
src/ResolvExpr/ConversionCost.h
rd9bad51 raf746cc 72 72 void postvisit( const ast::ZeroType * zeroType ); 73 73 void postvisit( const ast::OneType * oneType ); 74 void postvisit( const ast::Enum PosType * posType );74 void postvisit( const ast::EnumAttrType * posType ); 75 75 private: 76 76 // refactor for code resue -
src/ResolvExpr/Unify.cc
rd9bad51 raf746cc 274 274 void previsit( const ast::Node * ) { visit_children = false; } 275 275 276 void postvisit( const ast::VoidType * ) { 277 result = dynamic_cast< const ast::VoidType * >( type2 ); 276 void postvisit( const ast::VoidType * vt) { 277 result = dynamic_cast< const ast::VoidType * >( type2 ) 278 || tryToUnifyWithEnumValue(vt, type2, tenv, need, have, open, noWiden()); 279 ; 278 280 } 279 281 … … 282 284 result = basic->kind == basic2->kind; 283 285 } 286 result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden()); 284 287 } 285 288 … … 290 293 noWiden()); 291 294 } 295 result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden()); 292 296 } 293 297 … … 307 311 308 312 result = unifyExact( 309 array->base, array2->base, tenv, need, have, open, noWiden()); 313 array->base, array2->base, tenv, need, have, open, noWiden()) 314 || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden()); 310 315 } 311 316 … … 399 404 } 400 405 406 bool tryToUnifyWithEnumValue( const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 407 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 408 WidenMode widen) { 409 if ( auto attrType2 = dynamic_cast<const ast::EnumAttrType *>(type2)) { 410 if (attrType2->attr == ast::EnumAttribute::Value) { 411 return unifyExact( type1, attrType2->instance->base->base, env, need, have, open, 412 widen); 413 } else if (attrType2->attr == ast::EnumAttribute::Posn) { 414 return unifyExact( type1, attrType2->instance, env, need, have, open, widen ); 415 } 416 } 417 return false; 418 } 419 401 420 public: 402 421 void postvisit( const ast::FunctionType * func ) { … … 507 526 void postvisit( const ast::StructInstType * aggrType ) { 508 527 handleGenericRefType( aggrType, type2 ); 528 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 509 529 } 510 530 511 531 void postvisit( const ast::UnionInstType * aggrType ) { 512 532 handleGenericRefType( aggrType, type2 ); 533 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 513 534 } 514 535 515 536 void postvisit( const ast::EnumInstType * aggrType ) { 516 537 handleRefType( aggrType, type2 ); 517 } 518 519 void postvisit( const ast::EnumPosType * posType ) { 538 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 539 } 540 541 void postvisit( const ast::EnumAttrType * enumAttr ) { 520 542 // Lazy approach for now 521 auto otherPos = dynamic_cast< const ast::EnumPosType *>(type2);522 if ( otherPos) {523 if ( otherPos->instance->base->name == posType->instance->base->name )524 result = otherPos;525 } 543 if ( auto otherPos = dynamic_cast< const ast::EnumAttrType *>(type2) ) { 544 if ( enumAttr->match(otherPos) ) { 545 result = otherPos; 546 } 547 } 526 548 } 527 549 528 550 void postvisit( const ast::TraitInstType * aggrType ) { 529 551 handleRefType( aggrType, type2 ); 552 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 530 553 } 531 554 … … 536 559 this->result = otherInst; 537 560 } 561 result = result || tryToUnifyWithEnumValue(typeInst, type2, tenv, need, have, open, noWiden()); 538 562 } 539 563 … … 610 634 auto types2 = flatten( flat2 ); 611 635 612 result = unifyList( types, types2, tenv, need, have, open ); 613 } 614 615 void postvisit( const ast::VarArgsType * ) { 616 result = dynamic_cast< const ast::VarArgsType * >( type2 ); 617 } 618 619 void postvisit( const ast::ZeroType * ) { 620 result = dynamic_cast< const ast::ZeroType * >( type2 ); 621 } 622 623 void postvisit( const ast::OneType * ) { 624 result = dynamic_cast< const ast::OneType * >( type2 ); 636 result = unifyList( types, types2, tenv, need, have, open ) 637 || tryToUnifyWithEnumValue(tuple, type2, tenv, need, have, open, noWiden()); 638 } 639 640 void postvisit( const ast::VarArgsType * vat) { 641 result = dynamic_cast< const ast::VarArgsType * >( type2 ) 642 || tryToUnifyWithEnumValue(vat, type2, tenv, need, have, open, noWiden()); 643 } 644 645 void postvisit( const ast::ZeroType * zt) { 646 result = dynamic_cast< const ast::ZeroType * >( type2 ) 647 || tryToUnifyWithEnumValue(zt, type2, tenv, need, have, open, noWiden()); 648 } 649 650 void postvisit( const ast::OneType * ot) { 651 result = dynamic_cast< const ast::OneType * >( type2 ) 652 || tryToUnifyWithEnumValue(ot, type2, tenv, need, have, open, noWiden()); 625 653 } 626 654 };
Note: See TracChangeset
for help on using the changeset viewer.