Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r11094d9 rfae6f21  
    7676
    7777        namespace {
    78                 void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 ) {
    79                         Indenter indent = { Indenter::tabsize, indentAmt };
     78                void printAlts( const AltList &list, std::ostream &os, int indent = 0 ) {
    8079                        for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    8180                                i->print( os, indent );
     
    123122                                                )
    124123                                                mapPlace->second.isAmbiguous = true;
    125                                         } else {
    126                                                 PRINT(
    127                                                         std::cerr << "cost " << candidate->cost << " loses to " << mapPlace->second.candidate->cost << std::endl;
    128                                                 )
    129124                                        }
    130125                                } else {
     
    132127                                }
    133128                        }
     129
     130                        PRINT(
     131                                std::cerr << "there are " << selected.size() << " alternatives before elimination" << std::endl;
     132                        )
    134133
    135134                        // accept the alternatives that were unambiguous
     
    146145                        expr->get_result()->accept( global_renamer );
    147146                }
     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                }
    148154        } // namespace
    149 
    150         void referenceToRvalueConversion( Expression *& expr ) {
    151                 if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
    152                         // cast away reference from expr
    153                         expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
    154                 }
    155         }
    156155
    157156        template< typename InputIterator, typename OutputIterator >
     
    176175        }
    177176
    178         void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
     177        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune ) {
    179178                expr->accept( *this );
    180                 if ( failFast && alternatives.empty() ) {
     179                if ( alternatives.empty() ) {
    181180                        throw SemanticError( "No reasonable alternatives for expression ", expr );
    182181                }
     182                for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
     183                        if ( adjust ) {
     184                                adjustExprType( i->expr->get_result(), i->env, indexer );
     185                        }
     186                }
    183187                if ( prune ) {
    184                         auto oldsize = alternatives.size();
    185188                        PRINT(
    186189                                std::cerr << "alternatives before prune:" << std::endl;
     
    189192                        AltList::iterator oldBegin = alternatives.begin();
    190193                        pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ) );
    191                         if ( failFast && alternatives.begin() == oldBegin ) {
     194                        if ( alternatives.begin() == oldBegin ) {
    192195                                std::ostringstream stream;
    193196                                AltList winners;
    194197                                findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
    195                                 stream << "Cannot choose between " << winners.size() << " alternatives for expression\n";
     198                                stream << "Cannot choose between " << winners.size() << " alternatives for expression ";
    196199                                expr->print( stream );
    197                                 stream << "Alternatives are:\n";
    198                                 printAlts( winners, stream, 1 );
     200                                stream << "Alternatives are:";
     201                                printAlts( winners, stream, 8 );
    199202                                throw SemanticError( stream.str() );
    200203                        }
    201204                        alternatives.erase( oldBegin, alternatives.end() );
    202                         PRINT(
    203                                 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;
    204                         )
    205205                        PRINT(
    206206                                std::cerr << "there are " << alternatives.size() << " alternatives after elimination" << std::endl;
    207207                        )
    208                 }
    209                 // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
    210                 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
    211                         if ( adjust ) {
    212                                 adjustExprType( i->expr->get_result(), i->env, indexer );
    213                         }
    214208                }
    215209
     
    221215        }
    222216
    223         void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    224                 find( expr, true );
    225         }
    226 
    227         void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    228                 find( expr, true, false );
    229         }
    230 
    231         void AlternativeFinder::maybeFind( Expression * expr ) {
    232                 find( expr, true, true, false );
     217        void AlternativeFinder::findWithAdjustment( Expression *expr, bool prune ) {
     218                find( expr, true, prune );
    233219        }
    234220
     
    313299                Cost convCost = conversionCost( actualType, formalType, indexer, env );
    314300                PRINT(
    315                         std::cerr << std::endl << "cost is " << convCost << std::endl;
     301                        std::cerr << std::endl << "cost is" << convCost << std::endl;
    316302                )
    317303                if ( convCost == Cost::infinity ) {
     
    319305                }
    320306                convCost.incPoly( polyCost( formalType, env, indexer ) + polyCost( actualType, env, indexer ) );
    321                 PRINT(
    322                         std::cerr << "cost with polycost is " << convCost << std::endl;
    323                 )
    324307                return convCost;
    325308        }
     
    327310        Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
    328311                Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env );
    329 
    330                 // if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion.
    331                 // ignore poly cost for now, since this requires resolution of the cast to infer parameters and this
    332                 // does not currently work for the reason stated below.
     312                // if ( convCost != Cost::zero ) {
     313
     314                // xxx - temporary -- ignore poly cost, since this causes some polymorphic functions to be cast, which causes the specialize
     315                // pass to try to specialize them, which currently does not work. Once that is fixed, remove the next 3 lines and uncomment the
     316                // previous line.
    333317                Cost tmpCost = convCost;
    334318                tmpCost.incPoly( -tmpCost.get_polyCost() );
     
    373357                                if ( function->get_isVarArgs() ) {
    374358                                        convCost.incUnsafe();
    375                                         PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    376359                                        // convert reference-typed expressions to value-typed expressions
    377360                                        referenceToRvalueConversion( *actualExpr );
     
    382365                        }
    383366                        Type * formalType = (*formal)->get_type();
     367                        PRINT(
     368                                std::cerr << std::endl << "converting ";
     369                                actualType->print( std::cerr, 8 );
     370                                std::cerr << std::endl << " to ";
     371                                formalType->print( std::cerr, 8 );
     372                                std::cerr << std::endl << "environment is: ";
     373                                alt.env.print( std::cerr, 8 );
     374                                std::cerr << std::endl;
     375                        )
    384376                        convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
    385377                        ++formal; // can't be in for-loop update because of the continue
     
    489481                                Alternative newerAlt( newAlt );
    490482                                newerAlt.env = newEnv;
    491                                 assertf( (*candidate)->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( *candidate ).c_str() );
     483                                assert( (*candidate)->get_uniqueId() );
    492484                                DeclarationWithType *candDecl = static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) );
    493485
     
    515507                                        std::cerr << std::endl;
    516508                                )
     509                                ApplicationExpr *appExpr = static_cast< ApplicationExpr* >( newerAlt.expr );
    517510                                // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter).
    518                                 InferredParams * inferParameters = &newerAlt.expr->get_inferParams();
     511                                InferredParams * inferParameters = &appExpr->get_inferParams();
    519512                                for ( UniqueId id : cur->second.idChain ) {
    520513                                        inferParameters = (*inferParameters)[ id ].inferParams.get();
     
    581574                std::vector<unsigned> tupleEls;  /// Number of elements in current tuple element(s)
    582575
    583                 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have,
     576                ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 
    584577                                const OpenVarSet& openVars)
    585578                        : actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0),
    586579                          expls(), nextExpl(0), tupleEls() {}
    587 
     580               
    588581                /// Starts a new tuple expression
    589582                void beginTuple() {
     
    620613
    621614        /// Instantiates an argument to match a formal, returns false if no results left
    622         bool instantiateArgument( Type* formalType, Initializer* initializer,
    623                         const std::vector< AlternativeFinder >& args,
    624                         std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults,
     615        bool instantiateArgument( Type* formalType, Initializer* initializer, 
     616                        const std::vector< AlternativeFinder >& args, 
     617                        std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults, 
    625618                        const SymTab::Indexer& indexer ) {
    626619                if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     
    629622                        for ( Type* type : *tupleType ) {
    630623                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    631                                 if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) )
     624                                if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) ) 
    632625                                        return false;
    633626                        }
     
    658651                                                Type* argType = result.actuals.back().expr->get_result();
    659652                                                if ( result.tupleEls.back() == 1 && Tuples::isTtype( argType ) ) {
    660                                                         // the case where a ttype value is passed directly is special, e.g. for
     653                                                        // the case where a ttype value is passed directly is special, e.g. for 
    661654                                                        // argument forwarding purposes
    662655                                                        // xxx - what if passing multiple arguments, last of which is ttype?
    663                                                         // xxx - what would happen if unify was changed so that unifying tuple
     656                                                        // xxx - what would happen if unify was changed so that unifying tuple 
    664657                                                        // types flattened both before unifying lists? then pass in TupleType
    665658                                                        // (ttype) below.
     
    671664                                                }
    672665                                                // check unification for ttype before adding to final
    673                                                 if ( unify( ttype, argType, result.env, result.need, result.have,
     666                                                if ( unify( ttype, argType, result.env, result.need, result.have, 
    674667                                                                result.openVars, indexer ) ) {
    675668                                                        finalResults.push_back( std::move(result) );
     
    684677                                                aResult.env.addActual( actual.env, aResult.openVars );
    685678                                                Cost cost = actual.cost;
    686 
     679               
    687680                                                // explode argument
    688681                                                std::vector<Alternative> exploded;
    689682                                                Tuples::explode( actual, indexer, back_inserter( exploded ) );
    690 
     683                                               
    691684                                                // add exploded argument to tuple
    692685                                                for ( Alternative& aActual : exploded ) {
     
    706699                        return ! results.empty();
    707700                }
    708 
     701               
    709702                // iterate each current subresult
    710703                for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) {
     
    724717                                        std::cerr << std::endl;
    725718                                )
    726 
    727                                 if ( unify( formalType, actualType, result.env, result.need, result.have,
     719                               
     720                                if ( unify( formalType, actualType, result.env, result.need, result.have, 
    728721                                                result.openVars, indexer ) ) {
    729722                                        ++result.nextExpl;
     
    736729                                if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) {
    737730                                        if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) {
    738                                                 if ( unify( formalType, cnst->get_type(), result.env, result.need,
     731                                                if ( unify( formalType, cnst->get_type(), result.env, result.need, 
    739732                                                                result.have, result.openVars, indexer ) ) {
    740733                                                        nextResults.push_back( std::move(result.withArg( cnstExpr )) );
     
    791784                results.swap( nextResults );
    792785                nextResults.clear();
    793 
     786               
    794787                return ! results.empty();
    795788        }
    796789
    797790        template<typename OutputIterator>
    798         void AlternativeFinder::makeFunctionAlternatives( const Alternative &func,
    799                         FunctionType *funcType, const std::vector< AlternativeFinder > &args,
     791        void AlternativeFinder::makeFunctionAlternatives( const Alternative& func,
     792                        FunctionType* funcType, const std::vector< AlternativeFinder >& args,
    800793                        OutputIterator out ) {
    801794                OpenVarSet funcOpenVars;
    802795                AssertionSet funcNeed, funcHave;
    803                 TypeEnvironment funcEnv( func.env );
     796                TypeEnvironment funcEnv;
    804797                makeUnifiableVars( funcType, funcOpenVars, funcNeed );
    805                 // add all type variables as open variables now so that those not used in the parameter
     798                // add all type variables as open variables now so that those not used in the parameter 
    806799                // list are still considered open.
    807800                funcEnv.add( funcType->get_forall() );
     
    809802                if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) {
    810803                        // attempt to narrow based on expected target type
    811                         Type * returnType = funcType->get_returnVals().front()->get_type();
    812                         if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars,
     804                        Type* returnType = funcType->get_returnVals().front()->get_type();
     805                        if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 
    813806                                        indexer ) ) {
    814807                                // unification failed, don't pursue this function alternative
     
    822815                for ( DeclarationWithType* formal : funcType->get_parameters() ) {
    823816                        ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal );
    824                         if ( ! instantiateArgument(
     817                        if ( ! instantiateArgument( 
    825818                                        obj->get_type(), obj->get_init(), args, results, nextResults, indexer ) )
    826819                                return;
     
    904897
    905898                std::vector< AlternativeFinder > argAlternatives;
    906                 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
     899                findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 
    907900                        back_inserter( argAlternatives ) );
    908901
     
    912905
    913906                // find function operators
    914                 static NameExpr *opExpr = new NameExpr( "?()" );
    915907                AlternativeFinder funcOpFinder( indexer, env );
    916                 // it's ok if there aren't any defined function ops
    917                 funcOpFinder.maybeFind( opExpr);
     908                NameExpr *opExpr = new NameExpr( "?()" );
     909                try {
     910                        funcOpFinder.findWithAdjustment( opExpr );
     911                } catch( SemanticError &e ) {
     912                        // it's ok if there aren't any defined function ops
     913                }
    918914                PRINT(
    919915                        std::cerr << "known function ops:" << std::endl;
    920                         printAlts( funcOpFinder.alternatives, std::cerr, 1 );
     916                        printAlts( funcOpFinder.alternatives, std::cerr, 8 );
    921917                )
    922918
     
    934930                                                Alternative newFunc( *func );
    935931                                                referenceToRvalueConversion( newFunc.expr );
    936                                                 makeFunctionAlternatives( newFunc, function, argAlternatives,
     932                                                makeFunctionAlternatives( newFunc, function, argAlternatives, 
    937933                                                        std::back_inserter( candidates ) );
    938934                                        }
     
    943939                                                        Alternative newFunc( *func );
    944940                                                        referenceToRvalueConversion( newFunc.expr );
    945                                                         makeFunctionAlternatives( newFunc, function, argAlternatives,
     941                                                        makeFunctionAlternatives( newFunc, function, argAlternatives, 
    946942                                                                std::back_inserter( candidates ) );
    947943                                                } // if
    948944                                        } // if
    949                                 }
     945                                }                       
    950946                        } catch ( SemanticError &e ) {
    951947                                errors.append( e );
     
    962958                                try {
    963959                                        // check if type is a pointer to function
    964                                         if ( PointerType* pointer = dynamic_cast<PointerType*>(
     960                                        if ( PointerType* pointer = dynamic_cast<PointerType*>( 
    965961                                                        funcOp->expr->get_result()->stripReferences() ) ) {
    966                                                 if ( FunctionType* function =
     962                                                if ( FunctionType* function = 
    967963                                                                dynamic_cast<FunctionType*>( pointer->get_base() ) ) {
    968964                                                        Alternative newFunc( *funcOp );
    969965                                                        referenceToRvalueConversion( newFunc.expr );
    970                                                         makeFunctionAlternatives( newFunc, function, argAlternatives,
     966                                                        makeFunctionAlternatives( newFunc, function, argAlternatives, 
    971967                                                                std::back_inserter( candidates ) );
    972968                                                }
     
    10071003                candidates.splice( candidates.end(), alternatives );
    10081004
    1009                 // use a new list so that alternatives are not examined by addAnonConversions twice.
    1010                 AltList winners;
    1011                 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) );
     1005                findMinCost( candidates.begin(), candidates.end(), std::back_inserter( alternatives ) );
    10121006
    10131007                // function may return struct or union value, in which case we need to add alternatives for implicit
    10141008                // conversions to each of the anonymous members, must happen after findMinCost since anon conversions
    10151009                // are never the cheapest expression
    1016                 for ( const Alternative & alt : winners ) {
     1010                for ( const Alternative & alt : alternatives ) {
    10171011                        addAnonConversions( alt );
    10181012                }
    1019                 alternatives.splice( alternatives.begin(), winners );
    10201013
    10211014                if ( alternatives.empty() && targetType && ! targetType->isVoid() ) {
     
    10351028        bool isLvalue( Expression *expr ) {
    10361029                // xxx - recurse into tuples?
    1037                 return expr->result && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
     1030                return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
    10381031        }
    10391032
     
    11101103                                thisCost.incSafe( discardedValues );
    11111104                                Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost );
    1112                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
     1105                                // xxx - this doesn't work at the moment, since inferParameters requires an ApplicationExpr as the alternative.
     1106                                // Once this works, it should be possible to infer parameters on a cast expression and specialize any function.
     1107
     1108                                // inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
     1109                                candidates.emplace_back( std::move( newAlt ) );
    11131110                        } // if
    11141111                } // for
     
    11261123                AlternativeFinder finder( indexer, env );
    11271124                // don't prune here, since it's guaranteed all alternatives will have the same type
    1128                 finder.findWithoutPrune( castExpr->get_arg() );
     1125                // (giving the alternatives different types is half of the point of ConstructorExpr nodes)
     1126                finder.findWithAdjustment( castExpr->get_arg(), false );
    11291127                for ( Alternative & alt : finder.alternatives ) {
    11301128                        alternatives.push_back( Alternative(
     
    11651163                PRINT( std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl; )
    11661164                for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
    1167                         VariableExpr newExpr( *i );
     1165                        VariableExpr newExpr( *i, nameExpr->get_argName() );
    11681166                        alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    11691167                        PRINT(
     
    14001398                findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) );
    14011399                std::list< AltList > possibilities;
     1400                // TODO re-write to use iterative method
    14021401                combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) );
    14031402                for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) {
     
    14231422                // don't prune here, since it's guaranteed all alternatives will have the same type
    14241423                // (giving the alternatives different types is half of the point of ConstructorExpr nodes)
    1425                 finder.findWithoutPrune( ctorExpr->get_callExpr() );
     1424                finder.findWithAdjustment( ctorExpr->get_callExpr(), false );
    14261425                for ( Alternative & alt : finder.alternatives ) {
    14271426                        alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
     
    14601459                // O(N^2) checks of d-types with e-types
    14611460                for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
    1462                         Type * toType = resolveTypeof( initAlt.type->clone(), indexer );
     1461                        Type * toType = resolveTypeof( initAlt.type, indexer );
    14631462                        SymTab::validateType( toType, &indexer );
    14641463                        adjustExprType( toType, env, indexer );
     
    14891488                                        // count one safe conversion for each value that is thrown away
    14901489                                        thisCost.incSafe( discardedValues );
    1491                                         Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
    1492                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
     1490                                        candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
    14931491                                }
    14941492                        }
Note: See TracChangeset for help on using the changeset viewer.