Changes in src/ResolvExpr/Resolver.cc [4b7cce6:60aaa51d]
- File:
-
- 1 edited
-
src/ResolvExpr/Resolver.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r4b7cce6 r60aaa51d 35 35 #include "AST/Print.hpp" 36 36 #include "AST/SymbolTable.hpp" 37 #include "AST/Type.hpp"38 37 #include "Common/PassVisitor.h" // for PassVisitor 39 38 #include "Common/SemanticError.h" // for SemanticError … … 957 956 } 958 957 }; 959 } // anonymous namespace 960 961 /// Check if this expression is or includes a deleted expression 962 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 963 ast::Pass<DeleteFinder_new> finder; 964 expr->accept( finder ); 965 return finder.pass.delExpr; 966 } 967 968 namespace { 958 959 /// Check if this expression is or includes a deleted expression 960 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) { 961 ast::Pass<DeleteFinder_new> finder; 962 expr->accept( finder ); 963 return finder.pass.delExpr; 964 } 965 969 966 /// always-accept candidate filter 970 967 bool anyCandidate( const Candidate & ) { return true; } … … 1026 1023 1027 1024 // promote candidate.cvtCost to .cost 1028 promoteCvtCost( winners ); 1025 for ( CandidateRef & cand : winners ) { 1026 cand->cost = cand->cvtCost; 1027 } 1029 1028 1030 1029 // produce ambiguous errors, if applicable … … 1100 1099 StripCasts_new::strip( expr ); 1101 1100 } 1102 } // anonymous namespace 1103 1104 1105 ast::ptr< ast::Expr > resolveInVoidContext( 1106 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1107 ) { 1108 assertf( expr, "expected a non-null expression" ); 1109 1110 // set up and resolve expression cast to void 1111 ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr }; 1112 CandidateRef choice = findUnfinishedKindExpression( 1113 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); 1114 1115 // a cast expression has either 0 or 1 interpretations (by language rules); 1116 // if 0, an exception has already been thrown, and this code will not run 1117 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 1118 env = std::move( choice->env ); 1119 1120 return castExpr->arg; 1121 } 1122 1123 namespace { 1101 1102 /// Find the expression candidate that is the unique best match for `untyped` in a `void` 1103 /// context. 1104 ast::ptr< ast::Expr > resolveInVoidContext( 1105 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1106 ) { 1107 assertf( expr, "expected a non-null expression" ); 1108 1109 // set up and resolve expression cast to void 1110 ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr }; 1111 CandidateRef choice = findUnfinishedKindExpression( 1112 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); 1113 1114 // a cast expression has either 0 or 1 interpretations (by language rules); 1115 // if 0, an exception has already been thrown, and this code will not run 1116 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 1117 env = std::move( choice->env ); 1118 1119 return castExpr->arg; 1120 } 1121 1124 1122 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1125 1123 /// context. … … 1148 1146 } 1149 1147 1150 /// Resolve `untyped` to the single expression whose candidate is the best match1151 ast::ptr< ast::Expr > findSingleExpression(1152 const ast::Expr * untyped, const ast::SymbolTable & symtab1153 ) {1154 return findKindExpression( untyped, symtab );1155 }1156 1157 1148 /// Resolve `untyped` to the single expression whose candidate is the best match for the 1158 1149 /// given type. … … 1161 1152 ) { 1162 1153 assert( untyped && type ); 1163 ast::ptr< ast::Expr >castExpr = new ast::CastExpr{ untyped->location, untyped, type };1164 ast::ptr< ast::Expr > newExpr = find SingleExpression( castExpr, symtab );1154 const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type }; 1155 ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab ); 1165 1156 removeExtraneousCast( newExpr, symtab ); 1166 1157 return newExpr; … … 1198 1189 return false; 1199 1190 } 1200 1201 /// Advance a type itertor to the next mutex parameter1202 template<typename Iter>1203 inline bool nextMutex( Iter & it, const Iter & end ) {1204 while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }1205 return it != end;1206 }1207 1191 } 1208 1192 … … 1229 1213 void previsit( const ast::PointerType * ); 1230 1214 1231 const ast::ExprStmt * previsit( const ast::ExprStmt * );1232 const ast::AsmExpr * previsit( const ast::AsmExpr * );1233 const ast::AsmStmt * previsit( const ast::AsmStmt * );1234 const ast::IfStmt * previsit( const ast::IfStmt * );1235 const ast::WhileStmt * previsit( const ast::WhileStmt * );1236 const ast::ForStmt * previsit( const ast::ForStmt * );1237 const ast::SwitchStmt * previsit( const ast::SwitchStmt * );1238 const ast::CaseStmt * previsit( const ast::CaseStmt * );1239 const ast::BranchStmt * previsit( const ast::BranchStmt * );1240 const ast::ReturnStmt * previsit( const ast::ReturnStmt * );1241 const ast::ThrowStmt * previsit( const ast::ThrowStmt * );1242 const ast::CatchStmt * previsit( const ast::CatchStmt * );1243 const ast::WaitForStmt *previsit( const ast::WaitForStmt * );1244 1245 const ast::SingleInit * previsit( const ast::SingleInit * );1246 const ast::ListInit * previsit( const ast::ListInit * );1247 const ast::ConstructorInit *previsit( const ast::ConstructorInit * );1215 const ast::ExprStmt * previsit( const ast::ExprStmt * ); 1216 const ast::AsmExpr * previsit( const ast::AsmExpr * ); 1217 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 1218 const ast::IfStmt * previsit( const ast::IfStmt * ); 1219 const ast::WhileStmt * previsit( const ast::WhileStmt * ); 1220 const ast::ForStmt * previsit( const ast::ForStmt * ); 1221 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 1222 const ast::CaseStmt * previsit( const ast::CaseStmt * ); 1223 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 1224 const ast::ReturnStmt * previsit( const ast::ReturnStmt * ); 1225 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 1226 const ast::CatchStmt * previsit( const ast::CatchStmt * ); 1227 void previsit( const ast::WaitForStmt * ); 1228 1229 const ast::SingleInit * previsit( const ast::SingleInit * ); 1230 const ast::ListInit * previsit( const ast::ListInit * ); 1231 void previsit( const ast::ConstructorInit * ); 1248 1232 }; 1249 1233 … … 1397 1381 "expression." ); 1398 1382 1399 ast::ptr< ast::Expr >untyped =1383 const ast::Expr * untyped = 1400 1384 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1401 ast::ptr< ast::Expr > newExpr = find SingleExpression( untyped, symtab );1385 ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab ); 1402 1386 1403 1387 // case condition cannot have a cast in C, so it must be removed here, regardless of … … 1417 1401 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 1418 1402 // computed goto argument is void* 1419 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };1420 1403 branchStmt = ast::mutate_field( 1421 1404 branchStmt, &ast::BranchStmt::computedTarget, 1422 findSingleExpression( branchStmt->computedTarget, target, symtab ) ); 1405 findSingleExpression( 1406 branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 1407 symtab ) ); 1423 1408 } 1424 1409 return branchStmt; … … 1460 1445 } 1461 1446 1462 const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1463 visit_children = false; 1464 1465 // Resolve all clauses first 1466 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) { 1467 const ast::WaitForStmt::Clause & clause = stmt->clauses[i]; 1468 1469 ast::TypeEnvironment env; 1470 CandidateFinder funcFinder{ symtab, env }; 1471 1472 // Find all candidates for a function in canonical form 1473 funcFinder.find( clause.target.func, ResolvMode::withAdjustment() ); 1474 1475 if ( funcFinder.candidates.empty() ) { 1476 stringstream ss; 1477 ss << "Use of undeclared indentifier '"; 1478 ss << clause.target.func.strict_as< ast::NameExpr >()->name; 1479 ss << "' in call to waitfor"; 1480 SemanticError( stmt->location, ss.str() ); 1481 } 1482 1483 if ( clause.target.args.empty() ) { 1484 SemanticError( stmt->location, 1485 "Waitfor clause must have at least one mutex parameter"); 1486 } 1487 1488 // Find all alternatives for all arguments in canonical form 1489 std::vector< CandidateFinder > argFinders = 1490 funcFinder.findSubExprs( clause.target.args ); 1491 1492 // List all combinations of arguments 1493 std::vector< CandidateList > possibilities; 1494 combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) ); 1495 1496 // For every possible function: 1497 // * try matching the arguments to the parameters, not the other way around because 1498 // more arguments than parameters 1499 CandidateList funcCandidates; 1500 std::vector< CandidateList > argsCandidates; 1501 SemanticErrorException errors; 1502 for ( CandidateRef & func : funcFinder.candidates ) { 1503 try { 1504 auto pointerType = dynamic_cast< const ast::PointerType * >( 1505 func->expr->result->stripReferences() ); 1506 if ( ! pointerType ) { 1507 SemanticError( stmt->location, func->expr->result.get(), 1508 "candidate not viable: not a pointer type\n" ); 1509 } 1510 1511 auto funcType = pointerType->base.as< ast::FunctionType >(); 1512 if ( ! funcType ) { 1513 SemanticError( stmt->location, func->expr->result.get(), 1514 "candidate not viable: not a function type\n" ); 1515 } 1516 1517 { 1518 auto param = funcType->params.begin(); 1519 auto paramEnd = funcType->params.end(); 1520 1521 if( ! nextMutex( param, paramEnd ) ) { 1522 SemanticError( stmt->location, funcType, 1523 "candidate function not viable: no mutex parameters\n"); 1524 } 1525 } 1526 1527 CandidateRef func2{ new Candidate{ *func } }; 1528 // strip reference from function 1529 func2->expr = referenceToRvalueConversion( func->expr, func2->cost ); 1530 1531 // Each argument must be matched with a parameter of the current candidate 1532 for ( auto & argsList : possibilities ) { 1533 try { 1534 // Declare data structures needed for resolution 1535 ast::OpenVarSet open; 1536 ast::AssertionSet need, have; 1537 ast::TypeEnvironment resultEnv{ func->env }; 1538 // Add all type variables as open so that those not used in the 1539 // parameter list are still considered open 1540 resultEnv.add( funcType->forall ); 1541 1542 // load type variables from arguments into one shared space 1543 for ( auto & arg : argsList ) { 1544 resultEnv.simpleCombine( arg->env ); 1545 } 1546 1547 // Make sure we don't widen any existing bindings 1548 resultEnv.forbidWidening(); 1549 1550 // Find any unbound type variables 1551 resultEnv.extractOpenVars( open ); 1552 1553 auto param = funcType->params.begin(); 1554 auto paramEnd = funcType->params.end(); 1555 1556 unsigned n_mutex_param = 0; 1557 1558 // For every argument of its set, check if it matches one of the 1559 // parameters. The order is important 1560 for ( auto & arg : argsList ) { 1561 // Ignore non-mutex arguments 1562 if ( ! nextMutex( param, paramEnd ) ) { 1563 // We ran out of parameters but still have arguments. 1564 // This function doesn't match 1565 SemanticError( stmt->location, funcType, 1566 toString("candidate function not viable: too many mutex " 1567 "arguments, expected ", n_mutex_param, "\n" ) ); 1568 } 1569 1570 ++n_mutex_param; 1571 1572 // Check if the argument matches the parameter type in the current 1573 // scope 1574 ast::ptr< ast::Type > paramType = (*param)->get_type(); 1575 if ( 1576 ! unify( 1577 arg->expr->result, paramType, resultEnv, need, have, open, 1578 symtab ) 1579 ) { 1580 // Type doesn't match 1581 stringstream ss; 1582 ss << "candidate function not viable: no known conversion " 1583 "from '"; 1584 ast::print( ss, (*param)->get_type() ); 1585 ss << "' to '"; 1586 ast::print( ss, arg->expr->result ); 1587 ss << "' with env '"; 1588 ast::print( ss, resultEnv ); 1589 ss << "'\n"; 1590 SemanticError( stmt->location, funcType, ss.str() ); 1591 } 1592 1593 ++param; 1594 } 1595 1596 // All arguments match! 1597 1598 // Check if parameters are missing 1599 if ( nextMutex( param, paramEnd ) ) { 1600 do { 1601 ++n_mutex_param; 1602 ++param; 1603 } while ( nextMutex( param, paramEnd ) ); 1604 1605 // We ran out of arguments but still have parameters left; this 1606 // function doesn't match 1607 SemanticError( stmt->location, funcType, 1608 toString( "candidate function not viable: too few mutex " 1609 "arguments, expected ", n_mutex_param, "\n" ) ); 1610 } 1611 1612 // All parameters match! 1613 1614 // Finish the expressions to tie in proper environments 1615 finishExpr( func2->expr, resultEnv ); 1616 for ( CandidateRef & arg : argsList ) { 1617 finishExpr( arg->expr, resultEnv ); 1618 } 1619 1620 // This is a match, store it and save it for later 1621 funcCandidates.emplace_back( std::move( func2 ) ); 1622 argsCandidates.emplace_back( std::move( argsList ) ); 1623 1624 } catch ( SemanticErrorException & e ) { 1625 errors.append( e ); 1626 } 1627 } 1628 } catch ( SemanticErrorException & e ) { 1629 errors.append( e ); 1630 } 1631 } 1632 1633 // Make sure correct number of arguments 1634 if( funcCandidates.empty() ) { 1635 SemanticErrorException top( stmt->location, 1636 "No alternatives for function in call to waitfor" ); 1637 top.append( errors ); 1638 throw top; 1639 } 1640 1641 if( argsCandidates.empty() ) { 1642 SemanticErrorException top( stmt->location, 1643 "No alternatives for arguments in call to waitfor" ); 1644 top.append( errors ); 1645 throw top; 1646 } 1647 1648 if( funcCandidates.size() > 1 ) { 1649 SemanticErrorException top( stmt->location, 1650 "Ambiguous function in call to waitfor" ); 1651 top.append( errors ); 1652 throw top; 1653 } 1654 if( argsCandidates.size() > 1 ) { 1655 SemanticErrorException top( stmt->location, 1656 "Ambiguous arguments in call to waitfor" ); 1657 top.append( errors ); 1658 throw top; 1659 } 1660 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 1661 1662 // build new clause 1663 ast::WaitForStmt::Clause clause2; 1664 1665 clause2.target.func = funcCandidates.front()->expr; 1666 1667 clause2.target.args.reserve( clause.target.args.size() ); 1668 for ( auto arg : argsCandidates.front() ) { 1669 clause2.target.args.emplace_back( std::move( arg->expr ) ); 1670 } 1671 1672 // Resolve the conditions as if it were an IfStmt, statements normally 1673 clause2.cond = findSingleExpression( clause.cond, symtab ); 1674 clause2.stmt = clause.stmt->accept( *visitor ); 1675 1676 // set results into stmt 1677 auto n = mutate( stmt ); 1678 n->clauses[i] = std::move( clause2 ); 1679 stmt = n; 1680 } 1681 1682 if ( stmt->timeout.stmt ) { 1683 // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally 1684 ast::WaitForStmt::Timeout timeout2; 1685 1686 ast::ptr< ast::Type > target = 1687 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1688 timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab ); 1689 timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab ); 1690 timeout2.stmt = stmt->timeout.stmt->accept( *visitor ); 1691 1692 // set results into stmt 1693 auto n = mutate( stmt ); 1694 n->timeout = std::move( timeout2 ); 1695 stmt = n; 1696 } 1697 1698 if ( stmt->orElse.stmt ) { 1699 // resolve the condition like IfStmt, stmts normally 1700 ast::WaitForStmt::OrElse orElse2; 1701 1702 orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab ); 1703 orElse2.stmt = stmt->orElse.stmt->accept( *visitor ); 1704 1705 // set results into stmt 1706 auto n = mutate( stmt ); 1707 n->orElse = std::move( orElse2 ); 1708 stmt = n; 1709 } 1710 1711 return stmt; 1447 void Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1448 #warning unimplemented; Resolver port in progress 1449 (void)stmt; 1450 assert(false); 1712 1451 } 1713 1452 … … 1718 1457 // resolve initialization using the possibilities as determined by the `currentObject` 1719 1458 // cursor. 1720 ast:: ptr< ast::Expr >untyped = new ast::UntypedInitExpr{1459 ast::Expr * untyped = new ast::UntypedInitExpr{ 1721 1460 singleInit->location, singleInit->value, currentObject.getOptions() }; 1722 ast::ptr<ast::Expr> newExpr = find SingleExpression( untyped, symtab );1461 ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab ); 1723 1462 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 1724 1463 … … 1771 1510 // iterate designations and initializers in pairs, moving the cursor to the current 1772 1511 // designated object and resolving the initializer against that object 1773 listInit = ast::mutate_field_index( 1774 listInit, &ast::ListInit::designations, i, 1775 currentObject.findNext( listInit->designations[i] ) ); 1776 listInit = ast::mutate_field_index( 1777 listInit, &ast::ListInit::initializers, i, 1778 listInit->initializers[i]->accept( *visitor ) ); 1779 } 1780 1781 // move cursor out of brace-enclosed initializer-list 1782 currentObject.exitListInit(); 1512 #warning unimplemented; Resolver port in progress 1513 assert(false); 1514 } 1783 1515 1784 1516 visit_children = false; … … 1786 1518 } 1787 1519 1788 const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) { 1789 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor ); 1790 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor ); 1791 1792 // found a constructor - can get rid of C-style initializer 1793 // xxx - Rob suggests this field is dead code 1794 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr ); 1795 1796 // intrinsic single-parameter constructors and destructors do nothing. Since this was 1797 // implicitly generated, there's no way for it to have side effects, so get rid of it to 1798 // clean up generated code 1799 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) { 1800 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr ); 1801 } 1802 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) { 1803 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr ); 1804 } 1805 1806 return ctorInit; 1520 void Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) { 1521 #warning unimplemented; Resolver port in progress 1522 (void)ctorInit; 1523 assert(false); 1807 1524 } 1808 1525
Note:
See TracChangeset
for help on using the changeset viewer.