Changeset d67cdb7 for src/ResolvExpr


Ignore:
Timestamp:
Sep 26, 2017, 11:27:38 PM (7 years ago)
Author:
Peter A. Buhr <pabuhr@…>
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:
5dc26f5
Parents:
201aeb9
Message:

merge

Location:
src/ResolvExpr
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r201aeb9 rd67cdb7  
    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

    r201aeb9 rd67cdb7  
    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

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

    r201aeb9 rd67cdb7  
    2929        /// Checks types and binds syntactic constructs to typed representations
    3030        void resolve( std::list< Declaration * > translationUnit );
     31        void resolveDecl( Declaration *, const SymTab::Indexer &indexer );
    3132        Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
    3233        Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer );
     34        Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer );
    3335        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
    3436        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
  • src/ResolvExpr/TypeEnvironment.cc

    r201aeb9 rd67cdb7  
    123123                for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    124124                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
    125 ///       std::cout << "adding " << *theVar;
     125///       std::cerr << "adding " << *theVar;
    126126                                if ( theClass->type ) {
    127 ///         std::cout << " bound to ";
    128 ///         theClass->type->print( std::cout );
    129 ///         std::cout << std::endl;
     127///         std::cerr << " bound to ";
     128///         theClass->type->print( std::cerr );
     129///         std::cerr << std::endl;
    130130                                        sub.add( *theVar, theClass->type );
    131131                                } else if ( theVar != theClass->vars.begin() ) {
    132132                                        TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
    133 ///         std::cout << " bound to variable " << *theClass->vars.begin() << std::endl;
     133///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
    134134                                        sub.add( *theVar, newTypeInst );
    135135                                        delete newTypeInst;
Note: See TracChangeset for help on using the changeset viewer.