Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r3b58d91 rb6fe7e6  
    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                 }
    188176        }
    189177
     
    209197        }
    210198
    211         void AlternativeFinder::find( Expression *expr, bool adjust ) {
     199        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune ) {
    212200                expr->accept( *this );
    213201                if ( alternatives.empty() ) {
     
    219207                        }
    220208                }
    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                 )
     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                }
    241231
    242232                // Central location to handle gcc extension keyword for all expression types.
     
    246236        }
    247237
    248         void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    249                 find( expr, true );
     238        void AlternativeFinder::findWithAdjustment( Expression *expr, bool prune ) {
     239                find( expr, true, prune );
    250240        }
    251241
    252242        template< typename StructOrUnionType >
    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 
     243        void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string &name ) {
    257244                std::list< Declaration* > members;
    258245                aggInst->lookup( name, members );
     
    283270                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    284271                std::list< Expression* >& actuals = appExpr->get_args();
    285 
    286                 std::list< Type * > formalTypes;
    287                 std::list< Type * >::iterator formalType = formalTypes.end();
    288 
    289272                for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    290 
    291273                        PRINT(
    292274                                std::cerr << "actual expression:" << std::endl;
     
    297279                        std::list< DeclarationWithType* >::iterator startFormal = formal;
    298280                        Cost actualCost;
    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                                                 }
     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;
    314288                                        }
    315                                         formalTypes.clear();
    316                                         flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
    317                                         formalType = formalTypes.begin();
    318                                         ++formal;
    319289                                }
    320 
    321290                                PRINT(
    322291                                        std::cerr << std::endl << "converting ";
    323                                         (*actualType)->print( std::cerr, 8 );
     292                                        (*actual)->print( std::cerr, 8 );
    324293                                        std::cerr << std::endl << " to ";
    325294                                        (*formal)->get_type()->print( std::cerr, 8 );
    326295                                )
    327                                 Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env );
     296                                Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
    328297                                PRINT(
    329298                                        std::cerr << std::endl << "cost is" << newCost << std::endl;
     
    336305                                actualCost += newCost;
    337306
    338                                 convCost += Cost( 0, polyCost( *formalType, alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 );
    339 
    340                                 formalType++;
     307                                convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actual, alt.env, indexer ), 0 );
     308
     309                                formal++;
    341310                        }
    342311                        if ( actualCost != Cost( 0, 0, 0 ) ) {
     
    413382                */
    414383                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    415 
    416                 std::list< Type * > formalTypes;
    417                 std::list< Type * >::iterator formalType = formalTypes.end();
    418 
    419384                for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    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;
     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;
    434388                                }
    435389                                PRINT(
     
    437391                                        (*formal)->get_type()->print( std::cerr );
    438392                                        std::cerr << std::endl << "actual type is ";
    439                                         (*actualType)->print( std::cerr );
     393                                        (*actual)->print( std::cerr );
    440394                                        std::cerr << std::endl;
    441395                                )
    442                                 if ( ! unify( *formalType, *actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     396                                if ( ! unify( (*formal)->get_type(), *actual, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
    443397                                        return false;
    444398                                }
    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 
     399                                formal++;
     400                        }
     401                }
    453402                // Handling of default values
    454403                while ( formal != formals.end() ) {
     
    813762                        if ( agg->expr->get_results().size() == 1 ) {
    814763                                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_results().front() ) ) {
    815                                         addAggMembers( structInst, agg->expr, agg->cost, memberExpr->get_member() );
     764                                        addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    816765                                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_results().front() ) ) {
    817                                         addAggMembers( unionInst, agg->expr, agg->cost, memberExpr->get_member() );
     766                                        addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    818767                                } // if
    819768                        } // if
     
    842791                        renameTypes( alternatives.back().expr );
    843792                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( (*i)->get_type() ) ) {
    844                                 NameExpr nameExpr( "" );
    845                                 addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), &nameExpr );
     793                                addAggMembers( structInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
    846794                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( (*i)->get_type() ) ) {
    847                                 NameExpr nameExpr( "" );
    848                                 addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), &nameExpr );
     795                                addAggMembers( unionInst, &newExpr, Cost( 0, 0, 1 ), env, "" );
    849796                        } // if
    850797                } // for
     
    10671014                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    10681015        }
     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        }
    10691026} // namespace ResolvExpr
    10701027
Note: See TracChangeset for help on using the changeset viewer.