Changeset aefcc3b for src/ResolvExpr


Ignore:
Timestamp:
Sep 20, 2016, 4:14:13 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
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:
23b6643f
Parents:
8c49c0e
Message:

major change to instantiateFunction to match arguments against the formal parameter's structure rather than the reverse

Location:
src/ResolvExpr
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Alternative.cc

    r8c49c0e raefcc3b  
    3838        }
    3939
     40        Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( other.env ) {
     41                other.expr = nullptr;
     42        }
     43
     44        Alternative & Alternative::operator=( Alternative && other ) {
     45                if ( &other == this )  return *this;
     46                delete expr;
     47                cost = other.cost;
     48                cvtCost = other.cvtCost;
     49                expr = other.expr;
     50                env = other.env;
     51                other.expr = nullptr;
     52                return *this;
     53        }
     54
    4055        void Alternative::initialize( const Alternative &src, Alternative &dest ) {
    4156                dest.cost = src.cost;
  • src/ResolvExpr/Alternative.h

    r8c49c0e raefcc3b  
    3232                Alternative( const Alternative &other );
    3333                Alternative &operator=( const Alternative &other );
     34                Alternative( Alternative && other );
     35                Alternative &operator=( Alternative && other );
    3436                ~Alternative();
    3537
     
    4951                Type * res = expr->get_result();
    5052                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) {
    51                         if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( alt.expr ) ) {
     53                        if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) {
     54                                // can open tuple expr and dump its exploded components
    5255                                for ( Expression * expr : tupleExpr->get_exprs() ) {
    5356                                        explodeUnique( expr, alt, out );
    5457                                }
    5558                        } else {
     59                                // tuple type, but not tuple expr - need to refer to single instance of the argument
     60                                // expression and index into its components
    5661                                UniqueExpr * unq = new UniqueExpr( expr->clone() );
    5762                                for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
     
    6368                        }
    6469                } else {
     70                        // atomic (non-tuple) type - output a clone of the expression in a new alternative
    6571                        *out++ = Alternative( expr->clone(), alt.env, alt.cost, alt.cvtCost );
    6672                }
     
    6975        /// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type
    7076        template< typename OutputIterator >
    71         void explode( Alternative &alt, OutputIterator out ) {
     77        void explode( const Alternative &alt, OutputIterator out ) {
    7278                explodeUnique( alt.expr, alt, out );
    7379        }
     
    7581        // explode list of alternatives
    7682        template< typename OutputIterator >
    77         void explode( AltList & alts, OutputIterator out ) {
    78                 for ( Alternative & alt : alts ) {
     83        void explode( const AltList & alts, OutputIterator out ) {
     84                for ( const Alternative & alt : alts ) {
    7985                        explode( alt, out );
    8086                }
  • src/ResolvExpr/AlternativeFinder.cc

    r8c49c0e raefcc3b  
    371371        }
    372372
    373         bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave ) {
     373        /// instantiate a single argument by matching actuals from [actualIt, actualEnd) against formalType,
     374        /// producing expression(s) in out and their total cost in cost.
     375        template< typename AltIterator, typename OutputIterator >
     376        bool instantiateArgument( Type * formalType, Initializer * defaultValue, AltIterator & actualIt, AltIterator actualEnd, OpenVarSet & openVars, TypeEnvironment & resultEnv, AssertionSet & resultNeed, AssertionSet & resultHave, const SymTab::Indexer & indexer, Cost & cost, OutputIterator out ) {
     377                if ( TupleType * tupleType = dynamic_cast< TupleType * >( formalType ) ) {
     378                        // formalType is a TupleType - group actuals into a TupleExpr whose type unifies with the TupleType
     379                        TupleExpr * tupleExpr = new TupleExpr();
     380                        for ( Type * type : *tupleType ) {
     381                                if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( tupleExpr->get_exprs() ) ) ) {
     382                                        delete tupleExpr;
     383                                        return false;
     384                                }
     385                        }
     386                        tupleExpr->set_result( Tuples::makeTupleType( tupleExpr->get_exprs() ) );
     387                        *out++ = tupleExpr;
     388                } else if ( actualIt != actualEnd ) {
     389                        // both actualType and formalType are atomic (non-tuple) types - if they unify
     390                        // then accept actual as an argument, otherwise return false (fail to instantiate argument)
     391                        Expression * actual = actualIt->expr;
     392                        Type * actualType = actual->get_result();
     393                        PRINT(
     394                                std::cerr << "formal type is ";
     395                                formalType->print( std::cerr );
     396                                std::cerr << std::endl << "actual type is ";
     397                                actualType->print( std::cerr );
     398                                std::cerr << std::endl;
     399                        )
     400                        if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     401                                return false;
     402                        }
     403                        // move the expression from the alternative to the output iterator
     404                        *out++ = actual;
     405                        actualIt->expr = nullptr;
     406                        cost += actualIt->cost;
     407                        ++actualIt;
     408                } else {
     409                        // End of actuals - Handle default values
     410                        if ( SingleInit *si = dynamic_cast<SingleInit *>( defaultValue )) {
     411                                // so far, only constant expressions are accepted as default values
     412                                if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( si->get_value()) ) {
     413                                        if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) ) {
     414                                                if ( unify( formalType, cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     415                                                        // xxx - Don't know if this is right
     416                                                        *out++ = cnstexpr->clone();
     417                                                        return true;
     418                                                } // if
     419                                        } // if
     420                                } // if
     421                        } // if
     422                        return false;
     423                } // if
     424                return true;
     425        }
     426
     427        bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out ) {
    374428                simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );
    375429                // make sure we don't widen any existing bindings
     
    379433                resultEnv.extractOpenVars( openVars );
    380434
    381                 std::list< DeclarationWithType* >::iterator formal = formals.begin();
    382 
    383                 AltList newActuals;
    384                 explode( actuals, back_inserter( newActuals ) );
    385 
    386                 std::list< Type * > formalTypes;
    387                 std::list< Type * >::iterator formalType = formalTypes.end();
    388 
    389                 for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    390                         std::list< Type * > flatActualTypes;
    391                         flatten( actualExpr->expr->get_result(), back_inserter( flatActualTypes ) );
    392                         for ( std::list< Type* >::iterator actualType = flatActualTypes.begin(); actualType != flatActualTypes.end(); ++actualType, ++formalType ) {
    393                                 if ( formalType == formalTypes.end() ) {
    394                                         // the type of the formal parameter may be a tuple type. To make this easier to work with,
    395                                         // flatten the tuple type and traverse the resulting list of types, incrementing the formal
    396                                         // iterator once its types have been extracted. Once a particular formal parameter's type has
    397                                         // been exhausted load the next formal parameter's type.
    398                                         if ( formal == formals.end() ) {
    399                                                 return isVarArgs;
    400                                         }
    401                                         formalTypes.clear();
    402                                         flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
    403                                         formalType = formalTypes.begin();
    404                                         ++formal;
    405                                 }
    406                                 PRINT(
    407                                         std::cerr << "formal type is ";
    408                                         (*formalType)->print( std::cerr );
    409                                         std::cerr << std::endl << "actual type is ";
    410                                         (*actualType)->print( std::cerr );
    411                                         std::cerr << std::endl;
    412                                 )
    413                                 if ( ! unify( *formalType, *actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    414                                         return false;
    415                                 }
    416                         }
    417                 }
    418 
    419                 // xxx - a tuple type was not completely matched
    420                 // partially handle the tuple with default arguments??
    421                 if ( formalType != formalTypes.end() ) return false;
    422 
    423                 // Handling of default values
    424                 while ( formal != formals.end() ) {
    425                         if ( ObjectDecl *od = dynamic_cast<ObjectDecl *>( *formal ) )
    426                                 if ( SingleInit *si = dynamic_cast<SingleInit *>( od->get_init() ))
    427                                         // so far, only constant expressions are accepted as default values
    428                                         if ( ConstantExpr *cnstexpr = dynamic_cast<ConstantExpr *>( si->get_value()) )
    429                                                 if ( Constant *cnst = dynamic_cast<Constant *>( cnstexpr->get_constant() ) )
    430                                                         if ( unify( (*formal)->get_type(), cnst->get_type(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    431                                                                 // XXX Don't know if this is right
    432                                                                 actuals.push_back( Alternative( cnstexpr->clone(), env, Cost::zero ) );
    433                                                                 formal++;
    434                                                                 if ( formal == formals.end()) break;
    435                                                         }
    436                         return false;
     435                // flatten actuals so that each actual has an atomic (non-tuple) type
     436                AltList exploded;
     437                explode( actuals, back_inserter( exploded ) );
     438
     439                AltList::iterator actualExpr = exploded.begin();
     440                AltList::iterator actualEnd = exploded.end();
     441                for ( DeclarationWithType * formal : formals ) {
     442                        // match flattened actuals with formal parameters - actuals will be grouped to match
     443                        // with formals as appropriate
     444                        Cost cost;
     445                        std::list< Expression * > newExprs;
     446                        ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
     447                        if ( ! instantiateArgument( obj->get_type(), obj->get_init(), actualExpr, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( newExprs ) ) ) {
     448                                deleteAll( newExprs );
     449                                return false;
     450                        }
     451                        // success - produce argument as a new alternative
     452                        assert( newExprs.size() == 1 );
     453                        out.push_back( Alternative( newExprs.front(), resultEnv, cost ) );
     454                }
     455                if ( actualExpr != actualEnd ) {
     456                        // there are still actuals remaining, but we've run out of formal parameters to match against
     457                        // this is okay only if the function is variadic
     458                        if ( ! isVarArgs ) {
     459                                return false;
     460                        }
     461                        out.splice( out.end(), exploded, actualExpr, actualEnd );
    437462                }
    438463                return true;
     
    565590
    566591        template< typename OutputIterator >
    567         void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out ) {
     592        void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out ) {
    568593                OpenVarSet openVars;
    569594                AssertionSet resultNeed, resultHave;
    570595                TypeEnvironment resultEnv;
    571596                makeUnifiableVars( funcType, openVars, resultNeed );
    572                 if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave ) ) {
     597                AltList instantiatedActuals; // filled by instantiate function
     598                if ( instantiateFunction( funcType->get_parameters(), actualAlt, funcType->get_isVarArgs(), openVars, resultEnv, resultNeed, resultHave, instantiatedActuals ) ) {
    573599                        ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    574                         Alternative newAlt( appExpr, resultEnv, sumCost( actualAlt ) );
    575                         makeExprList( actualAlt, appExpr->get_args() );
     600                        Alternative newAlt( appExpr, resultEnv, sumCost( instantiatedActuals ) );
     601                        makeExprList( instantiatedActuals, appExpr->get_args() );
    576602                        PRINT(
    577603                                std::cerr << "need assertions:" << std::endl;
  • src/ResolvExpr/AlternativeFinder.h

    r8c49c0e raefcc3b  
    7878                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    7979                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
    80                 bool instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave );
     80                bool instantiateFunction( std::list< DeclarationWithType* >& formals, const AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave, AltList & out );
    8181                template< typename OutputIterator >
    82                 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, AltList &actualAlt, OutputIterator out );
     82                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const AltList &actualAlt, OutputIterator out );
    8383                template< typename OutputIterator >
    8484                void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
  • src/ResolvExpr/Unify.cc

    r8c49c0e raefcc3b  
    416416
    417417        void markAssertions( AssertionSet &assertion1, AssertionSet &assertion2, Type *type ) {
    418                 for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
     418                for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
    419419                        for ( std::list< DeclarationWithType* >::const_iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
    420420                                markAssertionSet( assertion1, *assert );
Note: See TracChangeset for help on using the changeset viewer.