Changes in src/ResolvExpr/Resolver.cc [2773ab8:2d11663]
- File:
-
- 1 edited
-
src/ResolvExpr/Resolver.cc (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r2773ab8 r2d11663 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 … … 1147 1146 } 1148 1147 1149 /// Resolve `untyped` to the single expression whose candidate is the best match1150 ast::ptr< ast::Expr > findSingleExpression(1151 const ast::Expr * untyped, const ast::SymbolTable & symtab1152 ) {1153 return findKindExpression( untyped, symtab );1154 }1155 1156 1148 /// Resolve `untyped` to the single expression whose candidate is the best match for the 1157 1149 /// given type. … … 1160 1152 ) { 1161 1153 assert( untyped && type ); 1162 ast::ptr< ast::Expr >castExpr = new ast::CastExpr{ untyped->location, untyped, type };1163 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 ); 1164 1156 removeExtraneousCast( newExpr, symtab ); 1165 1157 return newExpr; … … 1197 1189 return false; 1198 1190 } 1199 1200 /// Advance a type itertor to the next mutex parameter1201 template<typename Iter>1202 inline bool nextMutex( Iter & it, const Iter & end ) {1203 while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }1204 return it != end;1205 }1206 1191 } 1207 1192 … … 1228 1213 void previsit( const ast::PointerType * ); 1229 1214 1230 const ast::ExprStmt * previsit( const ast::ExprStmt * );1231 const ast::AsmExpr * previsit( const ast::AsmExpr * );1232 const ast::AsmStmt * previsit( const ast::AsmStmt * );1233 const ast::IfStmt * previsit( const ast::IfStmt * );1234 const ast::WhileStmt * previsit( const ast::WhileStmt * );1235 const ast::ForStmt * previsit( const ast::ForStmt * );1236 const ast::SwitchStmt * previsit( const ast::SwitchStmt * );1237 const ast::CaseStmt * previsit( const ast::CaseStmt * );1238 const ast::BranchStmt * previsit( const ast::BranchStmt * );1239 const ast::ReturnStmt * previsit( const ast::ReturnStmt * );1240 const ast::ThrowStmt * previsit( const ast::ThrowStmt * );1241 const ast::CatchStmt * previsit( const ast::CatchStmt * );1242 const ast::WaitForStmt *previsit( const ast::WaitForStmt * );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 * ); 1243 1228 1244 1229 const ast::SingleInit * previsit( const ast::SingleInit * ); … … 1396 1381 "expression." ); 1397 1382 1398 ast::ptr< ast::Expr >untyped =1383 const ast::Expr * untyped = 1399 1384 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1400 ast::ptr< ast::Expr > newExpr = find SingleExpression( untyped, symtab );1385 ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab ); 1401 1386 1402 1387 // case condition cannot have a cast in C, so it must be removed here, regardless of … … 1416 1401 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 1417 1402 // computed goto argument is void* 1418 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };1419 1403 branchStmt = ast::mutate_field( 1420 1404 branchStmt, &ast::BranchStmt::computedTarget, 1421 findSingleExpression( branchStmt->computedTarget, target, symtab ) ); 1405 findSingleExpression( 1406 branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 1407 symtab ) ); 1422 1408 } 1423 1409 return branchStmt; … … 1459 1445 } 1460 1446 1461 const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1462 visit_children = false; 1463 1464 // Resolve all clauses first 1465 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) { 1466 const ast::WaitForStmt::Clause & clause = stmt->clauses[i]; 1467 1468 ast::TypeEnvironment env; 1469 CandidateFinder funcFinder{ symtab, env }; 1470 1471 // Find all candidates for a function in canonical form 1472 funcFinder.find( clause.target.func, ResolvMode::withAdjustment() ); 1473 1474 if ( funcFinder.candidates.empty() ) { 1475 stringstream ss; 1476 ss << "Use of undeclared indentifier '"; 1477 ss << clause.target.func.strict_as< ast::NameExpr >()->name; 1478 ss << "' in call to waitfor"; 1479 SemanticError( stmt->location, ss.str() ); 1480 } 1481 1482 if ( clause.target.args.empty() ) { 1483 SemanticError( stmt->location, 1484 "Waitfor clause must have at least one mutex parameter"); 1485 } 1486 1487 // Find all alternatives for all arguments in canonical form 1488 std::vector< CandidateFinder > argFinders = 1489 funcFinder.findSubExprs( clause.target.args ); 1490 1491 // List all combinations of arguments 1492 std::vector< CandidateList > possibilities; 1493 combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) ); 1494 1495 // For every possible function: 1496 // * try matching the arguments to the parameters, not the other way around because 1497 // more arguments than parameters 1498 CandidateList funcCandidates; 1499 std::vector< CandidateList > argsCandidates; 1500 SemanticErrorException errors; 1501 for ( CandidateRef & func : funcFinder.candidates ) { 1502 try { 1503 auto pointerType = dynamic_cast< const ast::PointerType * >( 1504 func->expr->result->stripReferences() ); 1505 if ( ! pointerType ) { 1506 SemanticError( stmt->location, func->expr->result.get(), 1507 "candidate not viable: not a pointer type\n" ); 1508 } 1509 1510 auto funcType = pointerType->base.as< ast::FunctionType >(); 1511 if ( ! funcType ) { 1512 SemanticError( stmt->location, func->expr->result.get(), 1513 "candidate not viable: not a function type\n" ); 1514 } 1515 1516 { 1517 auto param = funcType->params.begin(); 1518 auto paramEnd = funcType->params.end(); 1519 1520 if( ! nextMutex( param, paramEnd ) ) { 1521 SemanticError( stmt->location, funcType, 1522 "candidate function not viable: no mutex parameters\n"); 1523 } 1524 } 1525 1526 CandidateRef func2{ new Candidate{ *func } }; 1527 // strip reference from function 1528 func2->expr = referenceToRvalueConversion( func->expr, func2->cost ); 1529 1530 // Each argument must be matched with a parameter of the current candidate 1531 for ( auto & argsList : possibilities ) { 1532 try { 1533 // Declare data structures needed for resolution 1534 ast::OpenVarSet open; 1535 ast::AssertionSet need, have; 1536 ast::TypeEnvironment resultEnv{ func->env }; 1537 // Add all type variables as open so that those not used in the 1538 // parameter list are still considered open 1539 resultEnv.add( funcType->forall ); 1540 1541 // load type variables from arguments into one shared space 1542 for ( auto & arg : argsList ) { 1543 resultEnv.simpleCombine( arg->env ); 1544 } 1545 1546 // Make sure we don't widen any existing bindings 1547 resultEnv.forbidWidening(); 1548 1549 // Find any unbound type variables 1550 resultEnv.extractOpenVars( open ); 1551 1552 auto param = funcType->params.begin(); 1553 auto paramEnd = funcType->params.end(); 1554 1555 unsigned n_mutex_param = 0; 1556 1557 // For every argument of its set, check if it matches one of the 1558 // parameters. The order is important 1559 for ( auto & arg : argsList ) { 1560 // Ignore non-mutex arguments 1561 if ( ! nextMutex( param, paramEnd ) ) { 1562 // We ran out of parameters but still have arguments. 1563 // This function doesn't match 1564 SemanticError( stmt->location, funcType, 1565 toString("candidate function not viable: too many mutex " 1566 "arguments, expected ", n_mutex_param, "\n" ) ); 1567 } 1568 1569 ++n_mutex_param; 1570 1571 // Check if the argument matches the parameter type in the current 1572 // scope 1573 ast::ptr< ast::Type > paramType = (*param)->get_type(); 1574 if ( 1575 ! unify( 1576 arg->expr->result, paramType, resultEnv, need, have, open, 1577 symtab ) 1578 ) { 1579 // Type doesn't match 1580 stringstream ss; 1581 ss << "candidate function not viable: no known conversion " 1582 "from '"; 1583 ast::print( ss, (*param)->get_type() ); 1584 ss << "' to '"; 1585 ast::print( ss, arg->expr->result ); 1586 ss << "' with env '"; 1587 ast::print( ss, resultEnv ); 1588 ss << "'\n"; 1589 SemanticError( stmt->location, funcType, ss.str() ); 1590 } 1591 1592 ++param; 1593 } 1594 1595 // All arguments match! 1596 1597 // Check if parameters are missing 1598 if ( nextMutex( param, paramEnd ) ) { 1599 do { 1600 ++n_mutex_param; 1601 ++param; 1602 } while ( nextMutex( param, paramEnd ) ); 1603 1604 // We ran out of arguments but still have parameters left; this 1605 // function doesn't match 1606 SemanticError( stmt->location, funcType, 1607 toString( "candidate function not viable: too few mutex " 1608 "arguments, expected ", n_mutex_param, "\n" ) ); 1609 } 1610 1611 // All parameters match! 1612 1613 // Finish the expressions to tie in proper environments 1614 finishExpr( func2->expr, resultEnv ); 1615 for ( CandidateRef & arg : argsList ) { 1616 finishExpr( arg->expr, resultEnv ); 1617 } 1618 1619 // This is a match, store it and save it for later 1620 funcCandidates.emplace_back( std::move( func2 ) ); 1621 argsCandidates.emplace_back( std::move( argsList ) ); 1622 1623 } catch ( SemanticErrorException & e ) { 1624 errors.append( e ); 1625 } 1626 } 1627 } catch ( SemanticErrorException & e ) { 1628 errors.append( e ); 1629 } 1630 } 1631 1632 // Make sure correct number of arguments 1633 if( funcCandidates.empty() ) { 1634 SemanticErrorException top( stmt->location, 1635 "No alternatives for function in call to waitfor" ); 1636 top.append( errors ); 1637 throw top; 1638 } 1639 1640 if( argsCandidates.empty() ) { 1641 SemanticErrorException top( stmt->location, 1642 "No alternatives for arguments in call to waitfor" ); 1643 top.append( errors ); 1644 throw top; 1645 } 1646 1647 if( funcCandidates.size() > 1 ) { 1648 SemanticErrorException top( stmt->location, 1649 "Ambiguous function in call to waitfor" ); 1650 top.append( errors ); 1651 throw top; 1652 } 1653 if( argsCandidates.size() > 1 ) { 1654 SemanticErrorException top( stmt->location, 1655 "Ambiguous arguments in call to waitfor" ); 1656 top.append( errors ); 1657 throw top; 1658 } 1659 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 1660 1661 // build new clause 1662 ast::WaitForStmt::Clause clause2; 1663 1664 clause2.target.func = funcCandidates.front()->expr; 1665 1666 clause2.target.args.reserve( clause.target.args.size() ); 1667 for ( auto arg : argsCandidates.front() ) { 1668 clause2.target.args.emplace_back( std::move( arg->expr ) ); 1669 } 1670 1671 // Resolve the conditions as if it were an IfStmt, statements normally 1672 clause2.cond = findSingleExpression( clause.cond, symtab ); 1673 clause2.stmt = clause.stmt->accept( *visitor ); 1674 1675 // set results into stmt 1676 auto n = mutate( stmt ); 1677 n->clauses[i] = std::move( clause2 ); 1678 stmt = n; 1679 } 1680 1681 if ( stmt->timeout.stmt ) { 1682 // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally 1683 ast::WaitForStmt::Timeout timeout2; 1684 1685 ast::ptr< ast::Type > target = 1686 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1687 timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab ); 1688 timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab ); 1689 timeout2.stmt = stmt->timeout.stmt->accept( *visitor ); 1690 1691 // set results into stmt 1692 auto n = mutate( stmt ); 1693 n->timeout = std::move( timeout2 ); 1694 stmt = n; 1695 } 1696 1697 if ( stmt->orElse.stmt ) { 1698 // resolve the condition like IfStmt, stmts normally 1699 ast::WaitForStmt::OrElse orElse2; 1700 1701 orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab ); 1702 orElse2.stmt = stmt->orElse.stmt->accept( *visitor ); 1703 1704 // set results into stmt 1705 auto n = mutate( stmt ); 1706 n->orElse = std::move( orElse2 ); 1707 stmt = n; 1708 } 1709 1710 return stmt; 1447 void Resolver_new::previsit( const ast::WaitForStmt * stmt ) { 1448 #warning unimplemented; Resolver port in progress 1449 (void)stmt; 1450 assert(false); 1711 1451 } 1712 1452 … … 1717 1457 // resolve initialization using the possibilities as determined by the `currentObject` 1718 1458 // cursor. 1719 ast:: ptr< ast::Expr >untyped = new ast::UntypedInitExpr{1459 ast::Expr * untyped = new ast::UntypedInitExpr{ 1720 1460 singleInit->location, singleInit->value, currentObject.getOptions() }; 1721 ast::ptr<ast::Expr> newExpr = find SingleExpression( untyped, symtab );1461 ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab ); 1722 1462 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >(); 1723 1463
Note:
See TracChangeset
for help on using the changeset viewer.