Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r8b11840 r8f98b78  
    4040#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    4141#include "typeops.h"                     // for extractResultType
     42#include "Unify.h"                       // for unify
    4243
    4344using namespace std;
     
    7172                void previsit( ThrowStmt *throwStmt );
    7273                void previsit( CatchStmt *catchStmt );
     74                void previsit( WaitForStmt * stmt );
    7375
    7476                void previsit( SingleInit *singleInit );
     
    9395                PassVisitor<Resolver> resolver;
    9496                acceptAll( translationUnit, resolver );
    95         }
    96 
    97         void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {
    98                 PassVisitor<Resolver> resolver( indexer );
    99                 maybeAccept( decl, resolver );
    10097        }
    10198
     
    121118        }
    122119
     120        Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
     121                TypeEnvironment env;
     122                AlternativeFinder finder( indexer, env );
     123                finder.find( untyped );
     124                #if 0
     125                if ( finder.get_alternatives().size() != 1 ) {
     126                        std::cout << "untyped expr is ";
     127                        untyped->print( std::cout );
     128                        std::cout << std::endl << "alternatives are:";
     129                        for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
     130                                i->print( std::cout );
     131                        } // for
     132                } // if
     133                #endif
     134                assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
     135                Alternative &choice = finder.get_alternatives().front();
     136                Expression *newExpr = choice.expr->clone();
     137                finishExpr( newExpr, choice.env );
     138                return newExpr;
     139        }
     140
    123141        namespace {
    124                 Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
    125                         TypeEnvironment env;
    126                         AlternativeFinder finder( indexer, env );
    127                         finder.find( untyped );
    128 #if 0
    129                         if ( finder.get_alternatives().size() != 1 ) {
    130                                 std::cout << "untyped expr is ";
    131                                 untyped->print( std::cout );
    132                                 std::cout << std::endl << "alternatives are:";
    133                                 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    134                                         i->print( std::cout );
    135                                 } // for
    136                         } // if
    137 #endif
    138                         assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
    139                         Alternative &choice = finder.get_alternatives().front();
    140                         Expression *newExpr = choice.expr->clone();
    141                         finishExpr( newExpr, choice.env );
    142                         return newExpr;
    143                 }
    144 
    145142                bool isIntegralType( Type *type ) {
    146143                        if ( dynamic_cast< EnumInstType * >( type ) ) {
     
    396393        }
    397394
     395        inline void resolveAsIf( Expression *& expr, SymTab::Indexer & indexer ) {
     396                if( !expr ) return;
     397                Expression * newExpr = findSingleExpression( expr, indexer );
     398                delete expr;
     399                expr = newExpr;
     400        }
     401
     402        inline void resolveAsType( Expression *& expr, Type * type, SymTab::Indexer & indexer ) {
     403                if( !expr ) return;
     404                Expression * newExpr = findSingleExpression( new CastExpr( expr, type ), indexer );
     405                delete expr;
     406                expr = newExpr;
     407        }
     408
     409        template< typename iterator_t >
     410        inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
     411                while( it != end && !(*it)->get_type()->get_mutex() ) {
     412                        it++;
     413                }
     414
     415                return it != end;
     416        }
     417
     418        void Resolver::previsit( WaitForStmt * stmt ) {
     419                visit_children = false;
     420
     421                // Resolve all clauses first
     422                for( auto& clause : stmt->clauses ) {
     423
     424                        TypeEnvironment env;
     425                        AlternativeFinder funcFinder( indexer, env );
     426
     427                        // Find all alternatives for a function in canonical form
     428                        funcFinder.findWithAdjustment( clause.target.function );
     429
     430                        if ( funcFinder.get_alternatives().empty() ) {
     431                                stringstream ss;
     432                                ss << "Use of undeclared indentifier '";
     433                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
     434                                ss << "' in call to waitfor";
     435                                throw SemanticError( ss.str() );
     436                        }
     437
     438                        // Find all alternatives for all arguments in canonical form
     439                        std::list< AlternativeFinder > argAlternatives;
     440                        funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
     441
     442                        // List all combinations of arguments
     443                        std::list< AltList > possibilities;
     444                        combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
     445
     446                        AltList                func_candidates;
     447                        std::vector< AltList > args_candidates;
     448
     449                        // For every possible function :
     450                        //      try matching the arguments to the parameters
     451                        //      not the other way around because we have more arguments than parameters
     452                        SemanticError errors;
     453                        for ( Alternative & func : funcFinder.get_alternatives() ) {
     454                                try {
     455                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
     456                                        if( !pointer ) {
     457                                                throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
     458                                        }
     459
     460                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
     461                                        if( !function ) {
     462                                                throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
     463                                        }
     464
     465
     466                                        {
     467                                                auto param     = function->parameters.begin();
     468                                                auto param_end = function->parameters.end();
     469
     470                                                if( !advance_to_mutex( param, param_end ) ) {
     471                                                        throw SemanticError("candidate function not viable: no mutex parameters\n", function);
     472                                                }
     473                                        }
     474
     475                                        Alternative newFunc( func );
     476                                        // Strip reference from function
     477                                        referenceToRvalueConversion( newFunc.expr );
     478
     479                                        // For all the set of arguments we have try to match it with the parameter of the current function alternative
     480                                        for ( auto & argsList : possibilities ) {
     481
     482                                                try {
     483                                                        // Declare data structures need for resolution
     484                                                        OpenVarSet openVars;
     485                                                        AssertionSet resultNeed, resultHave;
     486                                                        TypeEnvironment resultEnv;
     487
     488                                                        // Load type variables from arguemnts into one shared space
     489                                                        simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
     490
     491                                                        // Make sure we don't widen any existing bindings
     492                                                        for ( auto & i : resultEnv ) {
     493                                                                i.allowWidening = false;
     494                                                        }
     495
     496                                                        // Find any unbound type variables
     497                                                        resultEnv.extractOpenVars( openVars );
     498
     499                                                        auto param     = function->parameters.begin();
     500                                                        auto param_end = function->parameters.end();
     501
     502                                                        // For every arguments of its set, check if it matches one of the parameter
     503                                                        // The order is important
     504                                                        for( auto & arg : argsList ) {
     505
     506                                                                // Ignore non-mutex arguments
     507                                                                if( !advance_to_mutex( param, param_end ) ) {
     508                                                                        // We ran out of parameters but still have arguments
     509                                                                        // this function doesn't match
     510                                                                        throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
     511                                                                }
     512
     513                                                                // Check if the argument matches the parameter type in the current scope
     514                                                                if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
     515                                                                        // Type doesn't match
     516                                                                        stringstream ss;
     517                                                                        ss << "candidate function not viable: no known convertion from '";
     518                                                                        arg.expr->get_result()->print( ss );
     519                                                                        ss << "' to '";
     520                                                                        (*param)->get_type()->print( ss );
     521                                                                        ss << "'\n";
     522                                                                        throw SemanticError(ss.str(), function);
     523                                                                }
     524
     525                                                                param++;
     526                                                        }
     527
     528                                                        // All arguments match !
     529
     530                                                        // Check if parameters are missing
     531                                                        if( advance_to_mutex( param, param_end ) ) {
     532                                                                // We ran out of arguments but still have parameters left
     533                                                                // this function doesn't match
     534                                                                throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
     535                                                        }
     536
     537                                                        // All parameters match !
     538
     539                                                        // Finish the expressions to tie in the proper environments
     540                                                        finishExpr( newFunc.expr, resultEnv );
     541                                                        for( Alternative & alt : argsList ) {
     542                                                                finishExpr( alt.expr, resultEnv );
     543                                                        }
     544
     545                                                        // This is a match store it and save it for later
     546                                                        func_candidates.push_back( newFunc );
     547                                                        args_candidates.push_back( argsList );
     548
     549                                                }
     550                                                catch( SemanticError &e ) {
     551                                                        errors.append( e );
     552                                                }
     553                                        }
     554                                }
     555                                catch( SemanticError &e ) {
     556                                        errors.append( e );
     557                                }
     558                        }
     559
     560                        // Make sure we got the right number of arguments
     561                        if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
     562                        if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
     563                        if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
     564                        if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
     565
     566
     567                        // Swap the results from the alternative with the unresolved values.
     568                        // Alternatives will handle deletion on destruction
     569                        std::swap( clause.target.function, func_candidates.front().expr );
     570                        for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
     571                                std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
     572                        }
     573
     574                        // Resolve the conditions as if it were an IfStmt
     575                        // Resolve the statments normally
     576                        resolveAsIf( clause.condition, this->indexer );
     577                        clause.statement->accept( *visitor );
     578                }
     579
     580
     581                if( stmt->timeout.statement ) {
     582                        // Resolve the timeout as an size_t for now
     583                        // Resolve the conditions as if it were an IfStmt
     584                        // Resolve the statments normally
     585                        resolveAsType( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
     586                        resolveAsIf  ( stmt->timeout.condition, this->indexer );
     587                        stmt->timeout.statement->accept( *visitor );
     588                }
     589
     590                if( stmt->orelse.statement ) {
     591                        // Resolve the conditions as if it were an IfStmt
     592                        // Resolve the statments normally
     593                        resolveAsIf( stmt->orelse.condition, this->indexer );
     594                        stmt->orelse.statement->accept( *visitor );
     595                }
     596        }
     597
    398598        template< typename T >
    399599        bool isCharType( T t ) {
Note: See TracChangeset for help on using the changeset viewer.