Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    rb6fe7e6 r3b58d91  
    174174                        }
    175175                }
     176
     177                // flatten tuple type into list of types
     178                template< typename OutputIterator >
     179                void flatten( Type * type, OutputIterator out ) {
     180                        if ( TupleType * tupleType = dynamic_cast< TupleType * >( type ) ) {
     181                                for ( Type * t : *tupleType ) {
     182                                        flatten( t, out );
     183                                }
     184                        } else {
     185                                *out++ = type;
     186                        }
     187                }
    176188        }
    177189
     
    197209        }
    198210
    199         void AlternativeFinder::find( Expression *expr, bool adjust, bool prune ) {
     211        void AlternativeFinder::find( Expression *expr, bool adjust ) {
    200212                expr->accept( *this );
    201213                if ( alternatives.empty() ) {
     
    207219                        }
    208220                }
    209                 if ( prune ) {
    210                         PRINT(
    211                                 std::cerr << "alternatives before prune:" << std::endl;
    212                                 printAlts( alternatives, std::cerr );
    213                         )
    214                         AltList::iterator oldBegin = alternatives.begin();
    215                         pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ), indexer );
    216                         if ( alternatives.begin() == oldBegin ) {
    217                                 std::ostringstream stream;
    218                                 stream << "Can't choose between alternatives for expression ";
    219                                 expr->print( stream );
    220                                 stream << "Alternatives are:";
    221                                 AltList winners;
    222                                 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
    223                                 printAlts( winners, stream, 8 );
    224                                 throw SemanticError( stream.str() );
    225                         }
    226                         alternatives.erase( oldBegin, alternatives.end() );
    227                         PRINT(
    228                                 std::cerr << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
    229                         )
    230                 }
     221                PRINT(
     222                        std::cerr << "alternatives before prune:" << std::endl;
     223                        printAlts( alternatives, std::cerr );
     224                )
     225                AltList::iterator oldBegin = alternatives.begin();
     226                pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ), indexer );
     227                if ( alternatives.begin() == oldBegin ) {
     228                        std::ostringstream stream;
     229                        stream << "Can't choose between alternatives for expression ";
     230                        expr->print( stream );
     231                        stream << "Alternatives are:";
     232                        AltList winners;
     233                        findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
     234                        printAlts( winners, stream, 8 );
     235                        throw SemanticError( stream.str() );
     236                }
     237                alternatives.erase( oldBegin, alternatives.end() );
     238                PRINT(
     239                        std::cerr << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
     240                )
    231241
    232242                // Central location to handle gcc extension keyword for all expression types.
     
    236246        }
    237247
    238         void AlternativeFinder::findWithAdjustment( Expression *expr, bool prune ) {
    239                 find( expr, true, prune );
     248        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
     249                find( expr, true );
    240250        }
    241251
    242252        template< typename StructOrUnionType >
    243         void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string &name ) {
     253        void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, Expression * member ) {
     254                NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
     255                const std::string & name = nameExpr->get_name();
     256
    244257                std::list< Declaration* > members;
    245258                aggInst->lookup( name, members );
     
    270283                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    271284                std::list< Expression* >& actuals = appExpr->get_args();
     285
     286                std::list< Type * > formalTypes;
     287                std::list< Type * >::iterator formalType = formalTypes.end();
     288
    272289                for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
     290
    273291                        PRINT(
    274292                                std::cerr << "actual expression:" << std::endl;
     
    279297                        std::list< DeclarationWithType* >::iterator startFormal = formal;
    280298                        Cost actualCost;
    281                         for ( std::list< Type* >::iterator actual = (*actualExpr)->get_results().begin(); actual != (*actualExpr)->get_results().end(); ++actual ) {
    282                                 if ( formal == formals.end() ) {
    283                                         if ( function->get_isVarArgs() ) {
    284                                                 convCost += Cost( 1, 0, 0 );
    285                                                 break;
    286                                         } else {
    287                                                 return Cost::infinity;
     299                        for ( std::list< Type* >::iterator actualType = (*actualExpr)->get_results().begin(); actualType != (*actualExpr)->get_results().end(); ++actualType ) {
     300
     301                                // tuple handling code
     302                                if ( formalType == formalTypes.end() ) {
     303                                        // the type of the formal parameter may be a tuple type. To make this easier to work with,
     304                                        // flatten the tuple type and traverse the resulting list of types, incrementing the formal
     305                                        // iterator once its types have been extracted. Once a particular formal parameter's type has
     306                                        // been exhausted load the next formal parameter's type.
     307                                        if ( formal == formals.end() ) {
     308                                                if ( function->get_isVarArgs() ) {
     309                                                        convCost += Cost( 1, 0, 0 );
     310                                                        break;
     311                                                } else {
     312                                                        return Cost::infinity;
     313                                                }
    288314                                        }
     315                                        formalTypes.clear();
     316                                        flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
     317                                        formalType = formalTypes.begin();
     318                                        ++formal;
    289319                                }
     320
    290321                                PRINT(
    291322                                        std::cerr << std::endl << "converting ";
    292                                         (*actual)->print( std::cerr, 8 );
     323                                        (*actualType)->print( std::cerr, 8 );
    293324                                        std::cerr << std::endl << " to ";
    294325                                        (*formal)->get_type()->print( std::cerr, 8 );
    295326                                )
    296                                 Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
     327                                Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env );
    297328                                PRINT(
    298329                                        std::cerr << std::endl << "cost is" << newCost << std::endl;
     
    305336                                actualCost += newCost;
    306337
    307                                 convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actual, alt.env, indexer ), 0 );
    308 
    309                                 formal++;
     338                                convCost += Cost( 0, polyCost( *formalType, alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 );
     339
     340                                formalType++;
    310341                        }
    311342                        if ( actualCost != Cost( 0, 0, 0 ) ) {
     
    382413                */
    383414                std::list< DeclarationWithType* >::iterator formal = formals.begin();
     415
     416                std::list< Type * > formalTypes;
     417                std::list< Type * >::iterator formalType = formalTypes.end();
     418
    384419                for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    385                         for ( std::list< Type* >::iterator actual = actualExpr->expr->get_results().begin(); actual != actualExpr->expr->get_results().end(); ++actual ) {
    386                                 if ( formal == formals.end() ) {
    387                                         return isVarArgs;
     420                        std::list< Type* > & actualTypes = actualExpr->expr->get_results();
     421                        for ( std::list< Type* >::iterator actualType = actualTypes.begin(); actualType != actualTypes.end(); ++actualType ) {
     422                                if ( formalType == formalTypes.end() ) {
     423                                        // the type of the formal parameter may be a tuple type. To make this easier to work with,
     424                                        // flatten the tuple type and traverse the resulting list of types, incrementing the formal
     425                                        // iterator once its types have been extracted. Once a particular formal parameter's type has
     426                                        // been exhausted load the next formal parameter's type.
     427                                        if ( formal == formals.end() ) {
     428                                                return isVarArgs;
     429                                        }
     430                                        formalTypes.clear();
     431                                        flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
     432                                        formalType = formalTypes.begin();
     433                                        ++formal;
    388434                                }
    389435                                PRINT(
     
    391437                                        (*formal)->get_type()->print( std::cerr );
    392438                                        std::cerr << std::endl << "actual type is ";
    393                                         (*actual)->print( std::cerr );
     439                                        (*actualType)->print( std::cerr );
    394440                                        std::cerr << std::endl;
    395441                                )
    396                                 if ( ! unify( (*formal)->get_type(), *actual, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     442                                if ( ! unify( *formalType, *actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    397443                                        return false;
    398444                                }
    399                                 formal++;
    400                         }
    401                 }
     445                                ++formalType;
     446                        }
     447                }
     448
     449                // xxx - a tuple type was not completely matched
     450                // partially handle the tuple with default arguments??
     451                if ( formalType != formalTypes.end() ) return false;
     452
    402453                // Handling of default values
    403454                while ( formal != formals.end() ) {
     
    762813                        if ( agg->expr->get_results().size() == 1 ) {
    763814                                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_results().front() ) ) {
    764                                         addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
     815                                        addAggMembers( structInst, agg->expr, agg->cost, memberExpr->get_member() );
    765816                                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_results().front() ) ) {
    766                                         addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
     817                                        addAggMembers( unionInst, agg->expr, agg->cost, memberExpr->get_member() );
    767818                                } // if
    768819                        } // if
     
    791842                        renameTypes( alternatives.back().expr );
    792843                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( (*i)->get_type() ) ) {
    793                                 addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
     844                                NameExpr nameExpr( "" );
     845                                addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), &nameExpr );
    794846                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( (*i)->get_type() ) ) {
    795                                 addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
     847                                NameExpr nameExpr( "" );
     848                                addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), &nameExpr );
    796849                        } // if
    797850                } // for
     
    10141067                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    10151068        }
    1016 
    1017         void AlternativeFinder::visit( ConstructorExpr * ctorExpr ) {
    1018                 AlternativeFinder finder( indexer, env );
    1019                 // don't prune here, since it's guaranteed all alternatives will have the same type
    1020                 // (giving the alternatives different types is half of the point of ConstructorExpr nodes)
    1021                 finder.findWithAdjustment( ctorExpr->get_callExpr(), false );
    1022                 for ( Alternative & alt : finder.alternatives ) {
    1023                         alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
    1024                 }
    1025         }
    10261069} // namespace ResolvExpr
    10271070
Note: See TracChangeset for help on using the changeset viewer.