Changeset 1dcd9554 for src/ResolvExpr


Ignore:
Timestamp:
Sep 14, 2017, 3:42:14 PM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
310e5b7
Parents:
f92c696
Message:

First "working" implementation of waitfor

Location:
src/ResolvExpr
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    rf92c696 r1dcd9554  
    144144                        expr->get_result()->accept( global_renamer );
    145145                }
    146 
    147                 void referenceToRvalueConversion( Expression *& expr ) {
    148                         if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
    149                                 // cast away reference from expr
    150                                 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
    151                         }
    152                 }
    153146        } // namespace
     147
     148        void referenceToRvalueConversion( Expression *& expr ) {
     149                if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
     150                        // cast away reference from expr
     151                        expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
     152                }
     153        }
    154154
    155155        template< typename InputIterator, typename OutputIterator >
  • src/ResolvExpr/AlternativeFinder.h

    rf92c696 r1dcd9554  
    5050                const SymTab::Indexer &get_indexer() const { return indexer; }
    5151                const TypeEnvironment &get_environ() const { return env; }
     52
     53                /// Runs a new alternative finder on each element in [begin, end)
     54                /// and writes each alternative finder to out.
     55                template< typename InputIterator, typename OutputIterator >
     56                void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
    5257          private:
    5358                virtual void visit( ApplicationExpr *applicationExpr );
     
    8186                virtual void visit( StmtExpr *stmtExpr );
    8287                virtual void visit( UntypedInitExpr *initExpr );
    83                 /// Runs a new alternative finder on each element in [begin, end)
    84                 /// and writes each alternative finder to out.
    85                 template< typename InputIterator, typename OutputIterator >
    86                 void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
    8788
    8889                /// Adds alternatives for anonymous members
     
    108109
    109110        Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env );
     111        void referenceToRvalueConversion( Expression *& expr );
    110112
    111113        template< typename InputIterator, typename OutputIterator >
  • src/ResolvExpr/Resolver.cc

    rf92c696 r1dcd9554  
    3939#include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    4040#include "typeops.h"                     // for extractResultType
     41#include "Unify.h"                       // for unify
    4142
    4243using namespace std;
     
    7677                virtual void visit( ThrowStmt *throwStmt ) override;
    7778                virtual void visit( CatchStmt *catchStmt ) override;
     79                virtual void visit( WaitForStmt *waitforStmt ) override;
    7880
    7981                virtual void visit( SingleInit *singleInit ) override;
     
    410412        }
    411413
     414        inline void resolveAsIf( Expression *& expr, Resolver & resolver ) {
     415                if( !expr ) return;
     416                Expression * newExpr = findSingleExpression( expr, resolver );
     417                delete expr;
     418                expr = newExpr;
     419        }
     420
     421        inline void resolveAsType( Expression *& expr, Type * type, Resolver & resolver ) {
     422                if( !expr ) return;
     423                Expression * newExpr = findSingleExpression( new CastExpr( expr, type ), resolver );
     424                delete expr;
     425                expr = newExpr;
     426        }
     427
     428        template< typename iterator_t >
     429        inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
     430                while( it != end && !(*it)->get_type()->get_mutex() ) {
     431                        it++;
     432                }
     433
     434                return it != end;
     435        }
     436
     437        void Resolver::visit( WaitForStmt * stmt ) {
     438
     439                // Resolve all clauses first
     440                for( auto& clause : stmt->clauses ) {
     441
     442                        TypeEnvironment env;
     443                        AlternativeFinder funcFinder( *this, env );
     444
     445                        // Find all alternatives for a function in canonical form
     446                        funcFinder.findWithAdjustment( clause.target.function );
     447
     448                        if ( funcFinder.get_alternatives().empty() ) {
     449                                stringstream ss;
     450                                ss << "Use of undeclared indentifier '";
     451                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
     452                                ss << "' in call to waitfor";
     453                                throw SemanticError( ss.str() );
     454                        }
     455
     456                        // Find all alternatives for all arguments in canonical form
     457                        std::list< AlternativeFinder > argAlternatives;
     458                        funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
     459
     460                        // List all combinations of arguments
     461                        std::list< AltList > possibilities;
     462                        combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
     463
     464                        AltList                func_candidates;
     465                        std::vector< AltList > args_candidates;
     466
     467                        // For every possible function :
     468                        //      try matching the arguments to the parameters
     469                        //      not the other way around because we have more arguments than parameters
     470                        SemanticError errors;
     471                        for ( Alternative & func : funcFinder.get_alternatives() ) {
     472                                try {
     473                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
     474                                        if( !pointer ) {
     475                                                throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
     476                                        }
     477
     478                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
     479                                        if( !function ) {
     480                                                throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
     481                                        }
     482
     483
     484                                        {
     485                                                auto param     = function->parameters.begin();
     486                                                auto param_end = function->parameters.end();
     487
     488                                                if( !advance_to_mutex( param, param_end ) ) {
     489                                                        throw SemanticError("candidate function not viable: no mutex parameters\n", function);
     490                                                }
     491                                        }
     492
     493                                        Alternative newFunc( func );
     494                                        // Strip reference from function
     495                                        referenceToRvalueConversion( newFunc.expr );
     496
     497                                        // For all the set of arguments we have try to match it with the parameter of the current function alternative
     498                                        for ( auto & argsList : possibilities ) {
     499
     500                                                try {
     501                                                        // Declare data structures need for resolution
     502                                                        OpenVarSet openVars;
     503                                                        AssertionSet resultNeed, resultHave;
     504                                                        TypeEnvironment resultEnv;
     505
     506                                                        // Load type variables from arguemnts into one shared space
     507                                                        simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
     508
     509                                                        // Make sure we don't widen any existing bindings
     510                                                        for ( auto & i : resultEnv ) {
     511                                                                i.allowWidening = false;
     512                                                        }
     513
     514                                                        // Find any unbound type variables
     515                                                        resultEnv.extractOpenVars( openVars );
     516
     517                                                        auto param     = function->parameters.begin();
     518                                                        auto param_end = function->parameters.end();
     519
     520                                                        // For every arguments of its set, check if it matches one of the parameter
     521                                                        // The order is important
     522                                                        for( auto & arg : argsList ) {
     523
     524                                                                // Ignore non-mutex arguments
     525                                                                if( !advance_to_mutex( param, param_end ) ) {
     526                                                                        // We ran out of parameters but still have arguments
     527                                                                        // this function doesn't match
     528                                                                        throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
     529                                                                }
     530
     531                                                                // Check if the argument matches the parameter type in the current scope
     532                                                                if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, *this ) ) {
     533                                                                        // Type doesn't match
     534                                                                        stringstream ss;
     535                                                                        ss << "candidate function not viable: no known convertion from '";
     536                                                                        arg.expr->get_result()->print( ss );
     537                                                                        ss << "' to '";
     538                                                                        (*param)->get_type()->print( ss );
     539                                                                        ss << "'\n";
     540                                                                        throw SemanticError(ss.str(), function);
     541                                                                }
     542
     543                                                                param++;
     544                                                        }
     545
     546                                                        // All arguments match !
     547
     548                                                        // Check if parameters are missing
     549                                                        if( advance_to_mutex( param, param_end ) ) {
     550                                                                // We ran out of arguments but still have parameters left
     551                                                                // this function doesn't match
     552                                                                throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
     553                                                        }
     554
     555                                                        // All parameters match !
     556
     557                                                        // Finish the expressions to tie in the proper environments
     558                                                        finishExpr( newFunc.expr, resultEnv );
     559                                                        for( Alternative & alt : argsList ) {
     560                                                                finishExpr( alt.expr, resultEnv );
     561                                                        }
     562
     563                                                        // This is a match store it and save it for later
     564                                                        func_candidates.push_back( newFunc );
     565                                                        args_candidates.push_back( argsList );
     566
     567                                                }
     568                                                catch( SemanticError &e ) {
     569                                                        errors.append( e );
     570                                                }
     571                                        }
     572                                }
     573                                catch( SemanticError &e ) {
     574                                        errors.append( e );
     575                                }
     576                        }
     577
     578                        // Make sure we got the right number of arguments
     579                        if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
     580                        if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
     581                        if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
     582                        if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
     583
     584
     585                        // Swap the results from the alternative with the unresolved values.
     586                        // Alternatives will handle deletion on destruction
     587                        std::swap( clause.target.function, func_candidates.front().expr );
     588                        for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
     589                                std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
     590                        }
     591
     592                        // Resolve the conditions as if it were an IfStmt
     593                        // Resolve the statments normally
     594                        resolveAsIf( clause.condition, *this );
     595                        clause.statement->accept( *this );
     596                }
     597
     598
     599                if( stmt->timeout.statement ) {
     600                        // Resolve the timeout as an size_t for now
     601                        // Resolve the conditions as if it were an IfStmt
     602                        // Resolve the statments normally
     603                        resolveAsType( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), *this );
     604                        resolveAsIf  ( stmt->timeout.condition, *this );
     605                        stmt->timeout.statement->accept( *this );
     606                }
     607
     608                if( stmt->orelse.statement ) {
     609                        // Resolve the conditions as if it were an IfStmt
     610                        // Resolve the statments normally
     611                        resolveAsIf( stmt->orelse.condition, *this );
     612                        stmt->orelse.statement->accept( *this );
     613                }
     614        }
     615
    412616        template< typename T >
    413617        bool isCharType( T t ) {
Note: See TracChangeset for help on using the changeset viewer.