Ignore:
Timestamp:
Jun 10, 2019, 5:20:07 PM (5 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
5485e10
Parents:
6949c45
Message:

Add new resolver overload for WaitForStmt?

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r6949c45 r2773ab8  
    3535#include "AST/Print.hpp"
    3636#include "AST/SymbolTable.hpp"
     37#include "AST/Type.hpp"
    3738#include "Common/PassVisitor.h"          // for PassVisitor
    3839#include "Common/SemanticError.h"        // for SemanticError
     
    11461147                }
    11471148
     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
    11481156                /// Resolve `untyped` to the single expression whose candidate is the best match for the
    11491157                /// given type.
     
    11521160                ) {
    11531161                        assert( untyped && type );
    1154                         const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
    1155                         ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab );
     1162                        ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped->location, untyped, type };
     1163                        ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    11561164                        removeExtraneousCast( newExpr, symtab );
    11571165                        return newExpr;
     
    11891197                        return false;
    11901198                }
     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                }
    11911206        }
    11921207
     
    12131228                void previsit( const ast::PointerType * );
    12141229
    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 * );
     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 * );
    12281243
    12291244                const ast::SingleInit *      previsit( const ast::SingleInit * );
     
    13811396                                "expression." );
    13821397                       
    1383                         const ast::Expr * untyped =
     1398                        ast::ptr< ast::Expr > untyped =
    13841399                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1385                         ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab );
     1400                        ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
    13861401                       
    13871402                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     
    14011416                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    14021417                        // computed goto argument is void*
     1418                        ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
    14031419                        branchStmt = ast::mutate_field(
    14041420                                branchStmt, &ast::BranchStmt::computedTarget,
    1405                                 findSingleExpression(
    1406                                         branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} },
    1407                                         symtab ) );
     1421                                findSingleExpression( branchStmt->computedTarget, target, symtab ) );
    14081422                }
    14091423                return branchStmt;
     
    14451459        }
    14461460
    1447         void Resolver_new::previsit( const ast::WaitForStmt * stmt ) {
    1448                 #warning unimplemented; Resolver port in progress
    1449                 (void)stmt;
    1450                 assert(false);
     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;
    14511711        }
    14521712
     
    14571717                // resolve initialization using the possibilities as determined by the `currentObject`
    14581718                // cursor.
    1459                 ast::Expr * untyped = new ast::UntypedInitExpr{
     1719                ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
    14601720                        singleInit->location, singleInit->value, currentObject.getOptions() };
    1461                 ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab );
     1721                ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
    14621722                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    14631723
Note: See TracChangeset for help on using the changeset viewer.