Changeset 46da46b
- Timestamp:
- May 2, 2023, 3:44:31 AM (12 months ago)
- Branches:
- ast-experimental, master
- Children:
- 0c840fc
- Parents:
- 1ab773e0
- Location:
- src
- Files:
-
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
r1ab773e0 r46da46b 2331 2331 old->location, 2332 2332 GET_ACCEPT_1(arg, Expr), 2333 old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast 2333 old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast, 2334 (ast::CastExpr::CastKind) old->kind 2334 2335 ) 2335 2336 ); -
src/AST/Expr.cpp
r1ab773e0 r46da46b 186 186 // --- CastExpr 187 187 188 CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )189 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}188 CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g, CastKind kind ) 189 : Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ), kind( kind ) {} 190 190 191 191 bool CastExpr::get_lvalue() const { -
src/AST/Expr.hpp
r1ab773e0 r46da46b 55 55 const Expr * e ) 56 56 : decl( id ), declptr( declptr ), actualType( actual ), formalType( formal ), expr( e ) {} 57 58 operator bool() {return declptr;} 57 59 }; 58 60 … … 334 336 GeneratedFlag isGenerated; 335 337 338 enum CastKind { 339 Default, // C 340 Coerce, // reinterpret cast 341 Return // overload selection 342 }; 343 344 CastKind kind = Default; 345 336 346 CastExpr( const CodeLocation & loc, const Expr * a, const Type * to, 337 GeneratedFlag g = GeneratedCast ) : Expr( loc, to ), arg( a ), isGenerated( g) {}347 GeneratedFlag g = GeneratedCast, CastKind kind = Default ) : Expr( loc, to ), arg( a ), isGenerated( g ), kind( kind ) {} 338 348 /// Cast-to-void 339 CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast );349 CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast, CastKind kind = Default ); 340 350 341 351 /// Wrap a cast expression around an existing expression (always generated) -
src/AST/Type.hpp
r1ab773e0 r46da46b 454 454 bool operator==(const TypeEnvKey & other) const; 455 455 bool operator<(const TypeEnvKey & other) const; 456 }; 456 operator bool() {return base;} 457 }; 458 457 459 458 460 /// tuple type e.g. `[int, char]` -
src/AST/TypeEnvironment.cpp
r1ab773e0 r46da46b 135 135 } 136 136 } 137 sub.normalize();137 // sub.normalize(); 138 138 } 139 139 -
src/GenPoly/SpecializeNew.cpp
r1ab773e0 r46da46b 112 112 using namespace ResolvExpr; 113 113 ast::OpenVarSet openVars, closedVars; 114 ast::AssertionSet need, have; 115 findOpenVars( formalType, openVars, closedVars, need, have, FirstClosed ); 116 findOpenVars( actualType, openVars, closedVars, need, have, FirstOpen ); 114 ast::AssertionSet need, have; // unused 115 ast::TypeEnvironment env; // unused 116 // findOpenVars( formalType, openVars, closedVars, need, have, FirstClosed ); 117 findOpenVars( actualType, openVars, closedVars, need, have, env, FirstOpen ); 117 118 for ( const ast::OpenVarSet::value_type & openVar : openVars ) { 118 119 const ast::Type * boundType = subs->lookup( openVar.first ); … … 124 125 if ( closedVars.find( *inst ) == closedVars.end() ) { 125 126 return true; 127 } 128 else { 129 assertf(false, "closed: %s", inst->name.c_str()); 126 130 } 127 131 // Otherwise, the variable is bound to a concrete type. -
src/Parser/ExpressionNode.cc
r1ab773e0 r46da46b 544 544 }; // OperName 545 545 546 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) {546 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node, CastExpr::CastKind kind ) { 547 547 Type * targetType = maybeMoveBuildType( decl_node ); 548 548 if ( dynamic_cast< VoidType * >( targetType ) ) { 549 549 delete targetType; 550 return new CastExpr( maybeMoveBuild< Expression >(expr_node), false );550 return new CastExpr( maybeMoveBuild< Expression >(expr_node), false, kind ); 551 551 } else { 552 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType, false );552 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType, false, kind ); 553 553 } // if 554 554 } // build_cast -
src/Parser/ParseNode.h
r1ab773e0 r46da46b 189 189 DimensionExpr * build_dimensionref( const std::string * name ); 190 190 191 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );191 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node, CastExpr::CastKind kind = CastExpr::Default ); 192 192 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node ); 193 193 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ); -
src/Parser/parser.yy
r1ab773e0 r46da46b 905 905 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $5 ), maybeMoveBuildType( $3 ) ) ); } 906 906 | '(' RETURN type_no_function ')' cast_expression // CFA 907 { SemanticError( yylloc, "Return cast is currently unimplemented." ); $$ = nullptr; }907 { $$ = new ExpressionNode( build_cast( $3, $5, CastExpr::Return ) ); } 908 908 | '(' COERCE type_no_function ')' cast_expression // CFA 909 909 { SemanticError( yylloc, "Coerce cast is currently unimplemented." ); $$ = nullptr; } -
src/ResolvExpr/Candidate.hpp
r1ab773e0 r46da46b 91 91 92 92 /// Holdover behaviour from old `findMinCost` -- xxx -- can maybe be eliminated? 93 /* 93 94 static inline void promoteCvtCost( CandidateList & candidates ) { 94 95 for ( CandidateRef & r : candidates ) { … … 96 97 } 97 98 } 99 */ 98 100 99 101 void print( std::ostream & os, const Candidate & cand, Indenter indent = {} ); -
src/ResolvExpr/CandidateFinder.cpp
r1ab773e0 r46da46b 30 30 #include "Resolver.h" 31 31 #include "ResolveTypeof.h" 32 #include "WidenMode.h" 32 33 #include "SatisfyAssertions.hpp" 33 34 #include "typeops.h" // for adjustExprType, conversionCost, polyCost, specCost … … 700 701 // attempt to narrow based on expected target type 701 702 const ast::Type * returnType = funcType->returns.front(); 702 if ( ! unify( 703 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 704 ) { 705 // unification failed, do not pursue this candidate 706 return; 703 if ( selfFinder.strictMode ) { 704 if ( ! unifyExact( 705 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden(), symtab ) // xxx - is no widening correct? 706 ) { 707 // unification failed, do not pursue this candidate 708 return; 709 } 710 } 711 else { 712 if ( ! unify( 713 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 714 ) { 715 // unification failed, do not pursue this candidate 716 return; 717 } 707 718 } 708 719 } … … 825 836 826 837 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) { 827 addAggMembers( structInst, aggrExpr, *cand, Cost:: safe, "" );838 addAggMembers( structInst, aggrExpr, *cand, Cost::unsafe, "" ); 828 839 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 829 addAggMembers( unionInst, aggrExpr, *cand, Cost:: safe, "" );840 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 830 841 } 831 842 } … … 958 969 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) { 959 970 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 971 // if (!selfFinder.allowVoid && function->returns.empty()) continue; 960 972 CandidateRef newFunc{ new Candidate{ *func } }; 961 973 newFunc->expr = … … 1008 1020 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } 1009 1021 1022 // only keep the best matching intrinsic result to match C semantics (no unexpected narrowing/widening) 1023 // TODO: keep one for each set of argument candidates? 1024 Cost intrinsicCost = Cost::infinity; 1025 CandidateList intrinsicResult; 1026 1010 1027 // Compute conversion costs 1011 1028 for ( CandidateRef & withFunc : found ) { … … 1030 1047 if ( cvtCost != Cost::infinity ) { 1031 1048 withFunc->cvtCost = cvtCost; 1032 candidates.emplace_back( std::move( withFunc ) ); 1033 } 1034 } 1049 withFunc->cost += cvtCost; 1050 auto func = withFunc->expr.strict_as<ast::ApplicationExpr>()->func.as<ast::VariableExpr>(); 1051 if (func && func->var->linkage == ast::Linkage::Intrinsic) { 1052 if (withFunc->cost < intrinsicCost) { 1053 intrinsicResult.clear(); 1054 intrinsicCost = withFunc->cost; 1055 } 1056 if (withFunc->cost == intrinsicCost) { 1057 intrinsicResult.emplace_back(std::move(withFunc)); 1058 } 1059 } 1060 else { 1061 candidates.emplace_back( std::move( withFunc ) ); 1062 } 1063 } 1064 } 1065 spliceBegin( candidates, intrinsicResult ); 1035 1066 found = std::move( candidates ); 1036 1067 1037 1068 // use a new list so that candidates are not examined by addAnonConversions twice 1038 CandidateList winners = findMinCost( found );1039 promoteCvtCost( winners );1069 // CandidateList winners = findMinCost( found ); 1070 // promoteCvtCost( winners ); 1040 1071 1041 1072 // function may return a struct/union value, in which case we need to add candidates 1042 1073 // for implicit conversions to each of the anonymous members, which must happen after 1043 1074 // `findMinCost`, since anon conversions are never the cheapest 1044 for ( const CandidateRef & c : winners) {1075 for ( const CandidateRef & c : found ) { 1045 1076 addAnonConversions( c ); 1046 1077 } 1047 spliceBegin( candidates, winners ); 1048 1049 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 1078 // would this be too slow when we don't check cost anymore? 1079 spliceBegin( candidates, found ); 1080 1081 if ( candidates.empty() && targetType && ! targetType->isVoid() && !selfFinder.strictMode ) { 1050 1082 // If resolution is unsuccessful with a target type, try again without, since it 1051 1083 // will sometimes succeed when it wouldn't with a target type binding. … … 1093 1125 1094 1126 CandidateFinder finder( context, tenv, toType ); 1127 if (toType->isVoid()) { 1128 finder.allowVoid = true; 1129 } 1130 if ( castExpr->kind == ast::CastExpr::Return ) { 1131 finder.strictMode = true; 1132 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1133 1134 // return casts are eliminated (merely selecting an overload, no actual operation) 1135 candidates = std::move(finder.candidates); 1136 } 1095 1137 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1096 1138 … … 1098 1140 1099 1141 CandidateList matches; 1142 Cost minExprCost = Cost::infinity; 1143 Cost minCastCost = Cost::infinity; 1100 1144 for ( CandidateRef & cand : finder.candidates ) { 1101 1145 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; … … 1129 1173 // count one safe conversion for each value that is thrown away 1130 1174 thisCost.incSafe( discardedValues ); 1131 CandidateRef newCand = std::make_shared<Candidate>( 1132 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1133 copy( cand->env ), std::move( open ), std::move( need ), cand->cost, 1134 cand->cost + thisCost ); 1135 inferParameters( newCand, matches ); 1136 } 1137 } 1138 1139 // select first on argument cost, then conversion cost 1140 CandidateList minArgCost = findMinCost( matches ); 1141 promoteCvtCost( minArgCost ); 1142 candidates = findMinCost( minArgCost ); 1175 // select first on argument cost, then conversion cost 1176 if (cand->cost < minExprCost || cand->cost == minExprCost && thisCost < minCastCost) { 1177 minExprCost = cand->cost; 1178 minCastCost = thisCost; 1179 matches.clear(); 1180 1181 1182 } 1183 // ambiguous case, still output candidates to print in error message 1184 if (cand->cost == minExprCost && thisCost == minCastCost) { 1185 CandidateRef newCand = std::make_shared<Candidate>( 1186 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1187 copy( cand->env ), std::move( open ), std::move( need ), cand->cost + thisCost); 1188 // currently assertions are always resolved immediately so this should have no effect. 1189 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1190 // we may need to revisit the logic. 1191 inferParameters( newCand, matches ); 1192 } 1193 // else skip, better alternatives found 1194 1195 } 1196 } 1197 candidates = std::move(matches); 1198 1199 //CandidateList minArgCost = findMinCost( matches ); 1200 //promoteCvtCost( minArgCost ); 1201 //candidates = findMinCost( minArgCost ); 1143 1202 } 1144 1203 … … 1261 1320 1262 1321 CandidateRef newCand = std::make_shared<Candidate>( 1263 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1264 cost ); 1322 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, cost ); 1265 1323 1266 1324 if (newCand->expr->env) { … … 1407 1465 // candidates for true result 1408 1466 CandidateFinder finder2( context, tenv ); 1467 finder2.allowVoid = true; 1409 1468 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 1410 1469 if ( finder2.candidates.empty() ) return; … … 1412 1471 // candidates for false result 1413 1472 CandidateFinder finder3( context, tenv ); 1473 finder3.allowVoid = true; 1414 1474 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1415 1475 if ( finder3.candidates.empty() ) return; … … 1478 1538 void postvisit( const ast::ConstructorExpr * ctorExpr ) { 1479 1539 CandidateFinder finder( context, tenv ); 1540 finder.allowVoid = true; 1480 1541 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() ); 1481 1542 for ( CandidateRef & r : finder.candidates ) { … … 1594 1655 CandidateFinder finder( context, tenv, toType ); 1595 1656 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1657 1658 Cost minExprCost = Cost::infinity; 1659 Cost minCastCost = Cost::infinity; 1596 1660 for ( CandidateRef & cand : finder.candidates ) { 1597 1661 if(reason.code == NotFound) reason.code = NoMatch; … … 1631 1695 // count one safe conversion for each value that is thrown away 1632 1696 thisCost.incSafe( discardedValues ); 1633 CandidateRef newCand = std::make_shared<Candidate>( 1697 if (cand->cost < minExprCost || cand->cost == minExprCost && thisCost < minCastCost) { 1698 minExprCost = cand->cost; 1699 minCastCost = thisCost; 1700 matches.clear(); 1701 } 1702 // ambiguous case, still output candidates to print in error message 1703 if (cand->cost == minExprCost && thisCost == minCastCost) { 1704 CandidateRef newCand = std::make_shared<Candidate>( 1634 1705 new ast::InitExpr{ 1635 1706 initExpr->location, restructureCast( cand->expr, toType ), 1636 1707 initAlt.designation }, 1637 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost ); 1638 inferParameters( newCand, matches ); 1639 } 1708 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1709 // currently assertions are always resolved immediately so this should have no effect. 1710 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1711 // we may need to revisit the logic. 1712 inferParameters( newCand, matches ); 1713 } 1714 1715 } 1716 1640 1717 } 1641 1718 … … 1643 1720 1644 1721 // select first on argument cost, then conversion cost 1645 CandidateList minArgCost = findMinCost( matches ); 1646 promoteCvtCost( minArgCost ); 1647 candidates = findMinCost( minArgCost ); 1722 // CandidateList minArgCost = findMinCost( matches ); 1723 // promoteCvtCost( minArgCost ); 1724 // candidates = findMinCost( minArgCost ); 1725 candidates = std::move(matches); 1648 1726 } 1649 1727 … … 1724 1802 auto found = selected.find( mangleName ); 1725 1803 if ( found != selected.end() ) { 1726 if ( newCand->cost < found->second.candidate->cost ) { 1804 // tiebreaking by picking the lower cost on CURRENT expression 1805 // NOTE: this behavior is different from C semantics. 1806 // Specific remediations are performed for C operators at postvisit(UntypedExpr). 1807 // Further investigations may take place. 1808 if ( newCand->cost < found->second.candidate->cost 1809 || (newCand->cost == found->second.candidate->cost && newCand->cvtCost < found->second.candidate->cvtCost) ) { 1727 1810 PRINT( 1728 1811 std::cerr << "cost " << newCand->cost << " beats " … … 1731 1814 1732 1815 found->second = PruneStruct{ newCand }; 1733 } else if ( newCand->cost == found->second.candidate->cost ) {1816 } else if ( newCand->cost == found->second.candidate->cost && newCand->cvtCost == found->second.candidate->cvtCost) { 1734 1817 // if one of the candidates contains a deleted identifier, can pick the other, 1735 1818 // since deleted expressions should not be ambiguous if there is another option … … 1822 1905 */ 1823 1906 1824 if ( mode.prune ) { 1907 // if ( mode.prune ) { 1908 // optimization: don't prune for NameExpr since it never has cost 1909 if ( mode.prune && !dynamic_cast<const ast::NameExpr *>(expr)) { 1825 1910 // trim candidates to single best one 1826 1911 PRINT( -
src/ResolvExpr/CandidateFinder.hpp
r1ab773e0 r46da46b 33 33 const ast::TypeEnvironment & env; ///< Substitutions performed in this resolution 34 34 ast::ptr< ast::Type > targetType; ///< Target type for resolution 35 bool strictMode = false; ///< If set to true, requires targetType to be exact match (inside return cast) 36 bool allowVoid = false; ///< If set to true, allow void-returning function calls (only top level, cast to void and first in comma) 35 37 std::set< std::string > otypeKeys; /// different type may map to same key 36 38 -
src/ResolvExpr/CastCost.cc
r1ab773e0 r46da46b 229 229 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) { 230 230 PRINT( std::cerr << "compatible!" << std::endl; ) 231 if (dynamic_cast<const ast::ZeroType *>(dst) || dynamic_cast<const ast::OneType *>(dst)) { 232 return Cost::spec; 233 } 231 234 return Cost::zero; 232 235 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) { -
src/ResolvExpr/CommonType.cc
r1ab773e0 r46da46b 695 695 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) { 696 696 #warning remove casts when `commonTypes` moved to new AST 697 698 /* 697 699 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ]; 698 700 if ( … … 704 706 result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers }; 705 707 } 708 */ 709 ast::BasicType::Kind kind; 710 if (basic->kind != basic2->kind && !widen.first && !widen.second) return; 711 else if (!widen.first) kind = basic->kind; // widen.second 712 else if (!widen.second) kind = basic2->kind; 713 else kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)basic2->kind ]; 714 // xxx - what does qualifiers even do here?? 715 if ( (basic->qualifiers >= basic2->qualifiers || widen.first) 716 && (basic->qualifiers <= basic2->qualifiers || widen.second) ) { 717 result = new ast::BasicType{ kind, basic->qualifiers | basic2->qualifiers }; 718 } 719 706 720 } else if ( 707 721 dynamic_cast< const ast::ZeroType * >( type2 ) … … 710 724 #warning remove casts when `commonTypes` moved to new AST 711 725 ast::BasicType::Kind kind = (ast::BasicType::Kind)(int)commonTypes[ (BasicType::Kind)(int)basic->kind ][ (BasicType::Kind)(int)ast::BasicType::SignedInt ]; 712 if ( 713 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 726 /* 727 if ( // xxx - what does qualifier even do here?? 728 ( ( basic->qualifiers >= type2->qualifiers ) 714 729 || widen.first ) 715 && ( (kind != basic->kind && basic->qualifiers <= type2->qualifiers )730 && ( ( /* kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 716 731 || widen.second ) 717 ) { 718 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 732 ) 733 */ 734 if (widen.second) { 735 result = new ast::BasicType{ basic->kind, basic->qualifiers | type2->qualifiers }; 719 736 } 720 737 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { … … 744 761 auto entry = open.find( *var ); 745 762 if ( entry != open.end() ) { 763 // if (tenv.lookup(*var)) { 746 764 ast::AssertionSet need, have; 747 765 if ( ! tenv.bindVar( -
src/ResolvExpr/ConversionCost.cc
r1ab773e0 r46da46b 702 702 703 703 cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env ); 704 705 // xxx - should qualifiers be considered in pass-by-value? 706 /* 704 707 if ( refType->base->qualifiers == dst->qualifiers ) { 705 708 cost.incReference(); … … 709 712 cost.incUnsafe(); 710 713 } 714 */ 715 cost.incReference(); 711 716 } 712 717 … … 792 797 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 793 798 } 799 // this has the effect of letting any expr such as x+0, x+1 to be typed 800 // the same as x, instead of at least int. are we willing to sacrifice this little 801 // bit of coherence with C? 802 // TODO: currently this does not work when no zero/one overloads exist. Find a fix for it. 803 // cost = Cost::zero; 794 804 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) { 795 805 cost = Cost::zero; 796 806 // +1 for zero_t ->, +1 for disambiguation 797 807 cost.incSafe( maxIntCost + 2 ); 808 // assuming 0p is supposed to be used for pointers? 798 809 } 799 810 } … … 804 815 cost = Cost::zero; 805 816 } else if ( const ast::BasicType * dstAsBasic = 806 dynamic_cast< const ast::BasicType * >( dst ) ) { 817 dynamic_cast< const ast::BasicType * >( dst ) ) { 807 818 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ]; 808 819 if ( -1 == tableResult ) { … … 813 824 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 814 825 } 826 827 // cost = Cost::zero; 815 828 } 816 829 } -
src/ResolvExpr/FindOpenVars.cc
r1ab773e0 r46da46b 21 21 #include "AST/Pass.hpp" 22 22 #include "AST/Type.hpp" 23 #include "AST/TypeEnvironment.hpp" 23 24 #include "Common/PassVisitor.h" 24 25 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType (ptr ... 25 26 #include "SynTree/Type.h" // for Type, Type::ForallList, ArrayType 27 28 #include <iostream> 26 29 27 30 namespace ResolvExpr { … … 102 105 ast::AssertionSet & need; 103 106 ast::AssertionSet & have; 107 ast::TypeEnvironment & env; 104 108 bool nextIsOpen; 105 109 106 110 FindOpenVars_new( 107 111 ast::OpenVarSet & o, ast::OpenVarSet & c, ast::AssertionSet & n, 108 ast::AssertionSet & h, FirstMode firstIsOpen )109 : open( o ), closed( c ), need( n ), have( h ), nextIsOpen( firstIsOpen ) {}112 ast::AssertionSet & h, ast::TypeEnvironment & env, FirstMode firstIsOpen ) 113 : open( o ), closed( c ), need( n ), have( h ), env (env), nextIsOpen( firstIsOpen ) {} 110 114 111 115 void previsit( const ast::FunctionType * type ) { 112 116 // mark open/closed variables 113 117 if ( nextIsOpen ) { 118 // trying to remove this from resolver. 119 // occasionally used in other parts so not deleting right now. 120 121 // insert open variables unbound to environment. 122 env.add(type->forall); 123 114 124 for ( auto & decl : type->forall ) { 115 125 open[ *decl ] = ast::TypeData{ decl->base }; … … 137 147 void findOpenVars( 138 148 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 139 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {140 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, firstIsOpen };149 ast::AssertionSet & need, ast::AssertionSet & have, ast::TypeEnvironment & env, FirstMode firstIsOpen ) { 150 ast::Pass< FindOpenVars_new > finder{ open, closed, need, have, env, firstIsOpen }; 141 151 type->accept( finder ); 152 153 if (!closed.empty()) { 154 std::cerr << "closed: "; 155 for (auto& i : closed) { 156 std::cerr << i.first.base->location << ":" << i.first.base->name << ' '; 157 } 158 std::cerr << std::endl; 159 } 142 160 } 143 161 } // namespace ResolvExpr -
src/ResolvExpr/FindOpenVars.h
r1ab773e0 r46da46b 33 33 void findOpenVars( 34 34 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed, 35 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen );35 ast::AssertionSet & need, ast::AssertionSet & have, ast::TypeEnvironment & env, FirstMode firstIsOpen ); 36 36 } // namespace ResolvExpr 37 37 -
src/ResolvExpr/Resolver.cc
r1ab773e0 r46da46b 1009 1009 ast::TypeEnvironment env; 1010 1010 CandidateFinder finder( context, env ); 1011 finder.allowVoid = true; 1011 1012 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 1012 1013 --recursion_level; … … 1052 1053 1053 1054 // promote candidate.cvtCost to .cost 1054 promoteCvtCost( winners );1055 // promoteCvtCost( winners ); 1055 1056 1056 1057 // produce ambiguous errors, if applicable -
src/ResolvExpr/SatisfyAssertions.cpp
r1ab773e0 r46da46b 16 16 #include "SatisfyAssertions.hpp" 17 17 18 #include <iostream> 18 19 #include <algorithm> 19 20 #include <cassert> … … 42 43 #include "SymTab/Mangler.h" 43 44 45 46 44 47 namespace ResolvExpr { 45 48 … … 62 65 ast::AssertionSet && h, ast::AssertionSet && n, ast::OpenVarSet && o, ast::UniqueId rs ) 63 66 : cdata( c ), adjType( at ), env( std::move( e ) ), have( std::move( h ) ), 64 need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) {} 67 need( std::move( n ) ), open( std::move( o ) ), resnSlot( rs ) { 68 if (!have.empty()) { 69 std::cerr << c.id->location << ':' << c.id->name << std::endl; 70 } 71 } 65 72 }; 66 73 … … 136 143 }; 137 144 138 /// Adds a captured assertion to the symbol table 139 void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) { 140 for ( auto & i : have ) { 141 if ( i.second.isUsed ) { symtab.addId( i.first->var ); } 142 } 143 } 145 144 146 145 147 /// Binds a single assertion, updating satisfaction state … … 152 154 "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 153 155 154 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->c vtCost );156 ast::Expr * varExpr = match.cdata.combine( cand->expr->location, cand->cost ); 155 157 varExpr->result = match.adjType; 156 158 if ( match.resnSlot ) { varExpr->inferred.resnSlots().emplace_back( match.resnSlot ); } … … 162 164 163 165 /// Satisfy a single assertion 164 bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, boolskipUnbound = false) {166 bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool skipUnbound = false) { 165 167 // skip unused assertions 168 static unsigned int cnt = 0; 166 169 if ( ! assn.second.isUsed ) return true; 167 170 171 if (assn.first->var->name[1] == '|') std::cerr << ++cnt << std::endl; 172 168 173 // find candidates that unify with the desired type 169 AssnCandidateList matches ;174 AssnCandidateList matches, inexactMatches; 170 175 171 176 std::vector<ast::SymbolTable::IdData> candidates; … … 209 214 210 215 ast::OpenVarSet closed; 211 findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed ); 212 findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen ); 213 if ( allowConversion ) { 216 // findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed ); 217 findOpenVars( adjType, newOpen, closed, newNeed, have, newEnv, FirstOpen ); 218 ast::TypeEnvironment tempNewEnv {newEnv}; 219 220 if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) { 221 // set up binding slot for recursive assertions 222 ast::UniqueId crntResnSlot = 0; 223 if ( ! newNeed.empty() ) { 224 crntResnSlot = ++globalResnSlot; 225 for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; } 226 } 227 228 matches.emplace_back( 229 cdata, adjType, std::move( tempNewEnv ), std::move( have ), std::move( newNeed ), 230 std::move( newOpen ), crntResnSlot ); 231 } 232 else if ( matches.empty() ) { 233 // restore invalidated env 234 // newEnv = sat.cand->env; 235 // newNeed.clear(); 214 236 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) { 215 237 // set up binding slot for recursive assertions … … 220 242 } 221 243 222 matches.emplace_back(244 inexactMatches.emplace_back( 223 245 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ), 224 246 std::move( newOpen ), crntResnSlot ); 225 247 } 226 248 } 227 else {228 if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {229 // set up binding slot for recursive assertions230 ast::UniqueId crntResnSlot = 0;231 if ( ! newNeed.empty() ) {232 crntResnSlot = ++globalResnSlot;233 for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }234 }235 236 matches.emplace_back(237 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),238 std::move( newOpen ), crntResnSlot );239 }240 }241 249 } 242 250 243 251 // break if no satisfying match 252 if ( matches.empty() ) matches = std::move(inexactMatches); 244 253 if ( matches.empty() ) return false; 245 254 … … 252 261 // otherwise bind unique match in ongoing scope 253 262 AssnCandidate & match = matches.front(); 254 addToSymbolTable( match.have, sat.symtab );263 // addToSymbolTable( match.have, sat.symtab ); 255 264 sat.newNeed.insert( match.need.begin(), match.need.end() ); 256 265 sat.cand->env = std::move( match.env ); … … 435 444 // for each current mutually-compatible set of assertions 436 445 for ( SatState & sat : sats ) { 437 bool allowConversion = false;438 446 // stop this branch if a better option is already found 439 447 auto it = thresholds.find( pruneKey( *sat.cand ) ); … … 448 456 for ( auto & assn : sat.need ) { 449 457 // fail early if any assertion is not satisfiable 450 if ( ! satisfyAssertion( assn, sat, allowConversion,!next.empty() ) ) {458 if ( ! satisfyAssertion( assn, sat, !next.empty() ) ) { 451 459 next.emplace_back(assn); 452 460 // goto nextSat; … … 457 465 // fail if nothing resolves 458 466 else if (next.size() == sat.need.size()) { 459 if (allowConversion) {467 // if (allowConversion) { 460 468 Indenter tabs{ 3 }; 461 469 std::ostringstream ss; … … 467 475 errors.emplace_back( ss.str() ); 468 476 goto nextSat; 469 } 470 471 else { 472 allowConversion = true; 473 continue; 474 } 475 } 476 allowConversion = false; 477 // } 478 479 // else { 480 // allowConversion = true; 481 // continue; 482 // } 483 } 477 484 sat.need = std::move(next); 478 485 } … … 528 535 sat.cand->expr, std::move( compat.env ), std::move( compat.open ), 529 536 ast::AssertionSet{} /* need moved into satisfaction state */, 530 sat.cand->cost , sat.cand->cvtCost);537 sat.cand->cost ); 531 538 532 539 ast::AssertionSet nextNewNeed{ sat.newNeed }; … … 541 548 for ( DeferRef r : compat.assns ) { 542 549 AssnCandidate match = r.match; 543 addToSymbolTable( match.have, nextSymtab );550 // addToSymbolTable( match.have, nextSymtab ); 544 551 nextNewNeed.insert( match.need.begin(), match.need.end() ); 545 552 -
src/ResolvExpr/Unify.cc
r1ab773e0 r46da46b 134 134 env.apply( newSecond ); 135 135 136 findOpenVars( newFirst, open, closed, need, have, FirstClosed );137 findOpenVars( newSecond, open, closed, need, have, FirstOpen );136 // findOpenVars( newFirst, open, closed, need, have, FirstClosed ); 137 findOpenVars( newSecond, open, closed, need, have, newEnv, FirstOpen ); 138 138 139 139 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); … … 1029 1029 1030 1030 void postvisit( const ast::TypeInstType * typeInst ) { 1031 assert( open.find( *typeInst ) == open.end() );1031 // assert( open.find( *typeInst ) == open.end() ); 1032 1032 handleRefType( typeInst, type2 ); 1033 1033 } … … 1142 1142 ) { 1143 1143 ast::OpenVarSet closed; 1144 findOpenVars( type1, open, closed, need, have, FirstClosed );1145 findOpenVars( type2, open, closed, need, have, FirstOpen );1144 // findOpenVars( type1, open, closed, need, have, FirstClosed ); 1145 findOpenVars( type2, open, closed, need, have, env, FirstOpen ); 1146 1146 return unifyInexact( 1147 1147 type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common ); … … 1160 1160 entry1 = var1 ? open.find( *var1 ) : open.end(), 1161 1161 entry2 = var2 ? open.find( *var2 ) : open.end(); 1162 bool isopen1 = entry1 != open.end(); 1163 bool isopen2 = entry2 != open.end(); 1164 1162 // bool isopen1 = entry1 != open.end(); 1163 // bool isopen2 = entry2 != open.end(); 1164 bool isopen1 = var1 && env.lookup(*var1); 1165 bool isopen2 = var2 && env.lookup(*var2); 1166 1167 /* 1165 1168 if ( isopen1 && isopen2 ) { 1166 1169 if ( entry1->second.kind != entry2->second.kind ) return false; … … 1172 1175 } else if ( isopen2 ) { 1173 1176 return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab ); 1174 } else { 1177 } */ 1178 if ( isopen1 && isopen2 ) { 1179 if ( var1->base->kind != var2->base->kind ) return false; 1180 return env.bindVarToVar( 1181 var1, var2, ast::TypeData{ var1->base->kind, var1->base->sized||var2->base->sized }, need, have, 1182 open, widen, symtab ); 1183 } else if ( isopen1 ) { 1184 return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen, symtab ); 1185 } else if ( isopen2 ) { 1186 return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen, symtab ); 1187 }else { 1175 1188 return ast::Pass<Unify_new>::read( 1176 1189 type1, type2, env, need, have, open, widen, symtab ); 1177 1190 } 1191 1178 1192 } 1179 1193 -
src/SynTree/Expression.cc
r1ab773e0 r46da46b 267 267 } 268 268 269 CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {269 CastExpr::CastExpr( Expression * arg, Type * toType, bool isGenerated, CastKind kind ) : arg(arg), isGenerated( isGenerated ), kind( kind ) { 270 270 set_result(toType); 271 271 } 272 272 273 CastExpr::CastExpr( Expression * arg, bool isGenerated ) : arg(arg), isGenerated( isGenerated ) {273 CastExpr::CastExpr( Expression * arg, bool isGenerated, CastKind kind ) : arg(arg), isGenerated( isGenerated ), kind( kind ) { 274 274 set_result( new VoidType( Type::Qualifiers() ) ); 275 275 } 276 276 277 CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ) {277 CastExpr::CastExpr( const CastExpr & other ) : Expression( other ), arg( maybeClone( other.arg ) ), isGenerated( other.isGenerated ), kind( other.kind ) { 278 278 } 279 279 -
src/SynTree/Expression.h
r1ab773e0 r46da46b 271 271 bool isGenerated = true; 272 272 273 CastExpr( Expression * arg, bool isGenerated = true ); 274 CastExpr( Expression * arg, Type * toType, bool isGenerated = true ); 273 enum CastKind { 274 Default, // C 275 Coerce, // reinterpret cast 276 Return // overload selection 277 }; 278 279 CastKind kind = Default; 280 281 CastExpr( Expression * arg, bool isGenerated = true, CastKind kind = Default ); 282 CastExpr( Expression * arg, Type * toType, bool isGenerated = true, CastKind kind = Default ); 275 283 CastExpr( Expression * arg, void * ) = delete; // prevent accidentally passing pointers for isGenerated in the first constructor 276 284 CastExpr( const CastExpr & other ); -
src/Tuples/TupleAssignment.cc
r1ab773e0 r46da46b 679 679 680 680 ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env ); 681 finder.allowVoid = true; 681 682 682 683 try {
Note: See TracChangeset
for help on using the changeset viewer.