Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r60aaa51d r4b7cce6  
    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
     
    956957                        }
    957958                };
    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 
     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 {
    966969                /// always-accept candidate filter
    967970                bool anyCandidate( const Candidate & ) { return true; }
     
    10231026
    10241027                        // promote candidate.cvtCost to .cost
    1025                         for ( CandidateRef & cand : winners ) {
    1026                                 cand->cost = cand->cvtCost;
    1027                         }
     1028                        promoteCvtCost( winners );
    10281029
    10291030                        // produce ambiguous errors, if applicable
     
    10991100                        StripCasts_new::strip( expr );
    11001101                }
    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 
     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 {
    11221124                /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    11231125                /// context.
     
    11461148                }
    11471149
     1150                /// Resolve `untyped` to the single expression whose candidate is the best match
     1151                ast::ptr< ast::Expr > findSingleExpression(
     1152                        const ast::Expr * untyped, const ast::SymbolTable & symtab
     1153                ) {
     1154                        return findKindExpression( untyped, symtab );
     1155                }
     1156
    11481157                /// Resolve `untyped` to the single expression whose candidate is the best match for the
    11491158                /// given type.
     
    11521161                ) {
    11531162                        assert( untyped && type );
    1154                         const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
    1155                         ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab );
     1163                        ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped->location, untyped, type };
     1164                        ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    11561165                        removeExtraneousCast( newExpr, symtab );
    11571166                        return newExpr;
     
    11891198                        return false;
    11901199                }
     1200
     1201                /// Advance a type itertor to the next mutex parameter
     1202                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                }
    11911207        }
    11921208
     
    12131229                void previsit( const ast::PointerType * );
    12141230
    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 * );
     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 * );
    12321248        };
    12331249
     
    13811397                                "expression." );
    13821398                       
    1383                         const ast::Expr * untyped =
     1399                        ast::ptr< ast::Expr > untyped =
    13841400                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1385                         ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab );
     1401                        ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
    13861402                       
    13871403                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     
    14011417                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
    14021418                        // computed goto argument is void*
     1419                        ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };
    14031420                        branchStmt = ast::mutate_field(
    14041421                                branchStmt, &ast::BranchStmt::computedTarget,
    1405                                 findSingleExpression(
    1406                                         branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} },
    1407                                         symtab ) );
     1422                                findSingleExpression( branchStmt->computedTarget, target, symtab ) );
    14081423                }
    14091424                return branchStmt;
     
    14451460        }
    14461461
    1447         void Resolver_new::previsit( const ast::WaitForStmt * stmt ) {
    1448                 #warning unimplemented; Resolver port in progress
    1449                 (void)stmt;
    1450                 assert(false);
     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;
    14511712        }
    14521713
     
    14571718                // resolve initialization using the possibilities as determined by the `currentObject`
    14581719                // cursor.
    1459                 ast::Expr * untyped = new ast::UntypedInitExpr{
     1720                ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
    14601721                        singleInit->location, singleInit->value, currentObject.getOptions() };
    1461                 ast::ptr<ast::Expr> newExpr = findKindExpression( untyped, symtab );
     1722                ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
    14621723                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    14631724
     
    15101771                        // iterate designations and initializers in pairs, moving the cursor to the current
    15111772                        // designated object and resolving the initializer against that object
    1512                         #warning unimplemented; Resolver port in progress
    1513                         assert(false);
    1514                 }
     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();
    15151783
    15161784                visit_children = false;
     
    15181786        }
    15191787
    1520         void Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) {
    1521                 #warning unimplemented; Resolver port in progress
    1522                 (void)ctorInit;
    1523                 assert(false);
     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;
    15241807        }
    15251808
Note: See TracChangeset for help on using the changeset viewer.