Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r2773ab8 r2d11663  
    3535#include "AST/Print.hpp"
    3636#include "AST/SymbolTable.hpp"
    37 #include "AST/Type.hpp"
    3837#include "Common/PassVisitor.h"          // for PassVisitor
    3938#include "Common/SemanticError.h"        // for SemanticError
     
    11471146                }
    11481147
    1149                 /// Resolve `untyped` to the single expression whose candidate is the best match
    1150                 ast::ptr< ast::Expr > findSingleExpression(
    1151                         const ast::Expr * untyped, const ast::SymbolTable & symtab
    1152                 ) {
    1153                         return findKindExpression( untyped, symtab );
    1154                 }
    1155 
    11561148                /// Resolve `untyped` to the single expression whose candidate is the best match for the
    11571149                /// given type.
     
    11601152                ) {
    11611153                        assert( untyped && type );
    1162                         ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped->location, untyped, type };
    1163                         ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
     1154                        const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
     1155                        ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab );
    11641156                        removeExtraneousCast( newExpr, symtab );
    11651157                        return newExpr;
     
    11971189                        return false;
    11981190                }
    1199 
    1200                 /// Advance a type itertor to the next mutex parameter
    1201                 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                 }
    12061191        }
    12071192
     
    12281213                void previsit( const ast::PointerType * );
    12291214
    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 * );
    12431228
    12441229                const ast::SingleInit *      previsit( const ast::SingleInit * );
     
    13961381                                "expression." );
    13971382                       
    1398                         ast::ptr< ast::Expr > untyped =
     1383                        const ast::Expr * untyped =
    13991384                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1400                         ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
     1385                        ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab );
    14011386                       
    14021387                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     
    14161401                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    14171402                        // computed goto argument is void*
    1418                         ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
    14191403                        branchStmt = ast::mutate_field(
    14201404                                branchStmt, &ast::BranchStmt::computedTarget,
    1421                                 findSingleExpression( branchStmt->computedTarget, target, symtab ) );
     1405                                findSingleExpression(
     1406                                        branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} },
     1407                                        symtab ) );
    14221408                }
    14231409                return branchStmt;
     
    14591445        }
    14601446
    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);
    17111451        }
    17121452
     
    17171457                // resolve initialization using the possibilities as determined by the `currentObject`
    17181458                // cursor.
    1719                 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
     1459                ast::Expr * untyped = new ast::UntypedInitExpr{
    17201460                        singleInit->location, singleInit->value, currentObject.getOptions() };
    1721                 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
     1461                ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab );
    17221462                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    17231463
Note: See TracChangeset for help on using the changeset viewer.