Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r322b97e r5ccb10d  
    6767
    6868        Cost sumCost( const AltList &in ) {
    69                 Cost total;
     69                Cost total = Cost::zero;
    7070                for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
    7171                        total += i->cost;
     
    144144                        expr->get_result()->accept( global_renamer );
    145145                }
    146         }
     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                }
     153        } // namespace
    147154
    148155        template< typename InputIterator, typename OutputIterator >
     
    186193                        if ( alternatives.begin() == oldBegin ) {
    187194                                std::ostringstream stream;
    188                                 stream << "Can't choose between " << alternatives.size() << " alternatives for expression ";
     195                                AltList winners;
     196                                findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
     197                                stream << "Can't choose between " << winners.size() << " alternatives for expression ";
    189198                                expr->print( stream );
    190199                                stream << "Alternatives are:";
    191                                 AltList winners;
    192                                 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
    193200                                printAlts( winners, stream, 8 );
    194201                                throw SemanticError( stream.str() );
     
    213220        void AlternativeFinder::addAnonConversions( const Alternative & alt ) {
    214221                // adds anonymous member interpretations whenever an aggregate value type is seen.
    215                 Expression * expr = alt.expr->clone();
    216                 std::unique_ptr< Expression > manager( expr ); // RAII for expr
    217                 alt.env.apply( expr->get_result() );
    218                 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( expr->get_result() ) ) {
     222                // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
     223                std::unique_ptr<Expression> aggrExpr( alt.expr->clone() );
     224                alt.env.apply( aggrExpr->get_result() );
     225                Type * aggrType = aggrExpr->get_result();
     226                if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
     227                        aggrType = aggrType->stripReferences();
     228                        aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
     229                }
     230
     231                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    219232                        NameExpr nameExpr( "" );
    220                         addAggMembers( structInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );
    221                 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( expr->get_result() ) ) {
     233                        addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
     234                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    222235                        NameExpr nameExpr( "" );
    223                         addAggMembers( unionInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );
     236                        addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
    224237                } // if
    225238        }
     
    228241        void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    229242                // by this point, member must be a name expr
    230                 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
     243                NameExpr * nameExpr = dynamic_cast< NameExpr * >( member );
     244                if ( ! nameExpr ) return;
    231245                const std::string & name = nameExpr->get_name();
    232246                std::list< Declaration* > members;
     
    250264                        // during parsing and reusing that information here.
    251265                        std::stringstream ss( constantExpr->get_constant()->get_value() );
    252                         int val;
     266                        int val = 0;
    253267                        std::string tmp;
    254268                        if ( ss >> val && ! (ss >> tmp) ) {
     
    277291                FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    278292
    279                 Cost convCost( 0, 0, 0 );
     293                Cost convCost = Cost::zero;
    280294                std::list< DeclarationWithType* >& formals = function->get_parameters();
    281295                std::list< DeclarationWithType* >::iterator formal = formals.begin();
     
    290304                                actualType->print( std::cerr, 8 );
    291305                        )
    292                         Cost actualCost;
     306                        Cost actualCost = Cost::zero;
    293307                        if ( formal == formals.end() ) {
    294308                                if ( function->get_isVarArgs() ) {
    295                                         convCost += Cost( 1, 0, 0 );
     309                                        convCost.incUnsafe();
     310                                        // convert reference-typed expressions to value-typed expressions
     311                                        referenceToRvalueConversion( *actualExpr );
    296312                                        continue;
    297313                                } else {
     
    305321                                std::cerr << std::endl << " to ";
    306322                                formalType->print( std::cerr, 8 );
     323                                std::cerr << std::endl << "environment is: ";
     324                                alt.env.print( std::cerr, 8 );
     325                                std::cerr << std::endl;
    307326                        )
    308327                        Cost newCost = conversionCost( actualType, formalType, indexer, alt.env );
     
    316335                        convCost += newCost;
    317336                        actualCost += newCost;
    318                         if ( actualCost != Cost( 0, 0, 0 ) ) {
     337                        if ( actualCost != Cost::zero ) {
    319338                                Type *newType = formalType->clone();
    320339                                alt.env.apply( newType );
    321340                                *actualExpr = new CastExpr( *actualExpr, newType );
    322341                        }
    323                         convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0 );
     342                        convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) );
    324343                        ++formal; // can't be in for-loop update because of the continue
    325344                }
     
    343362                        }
    344363                        convCost += newCost;
    345                         convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0 );
     364                        convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) );
    346365                }
    347366
     
    400419                        Expression * actual = actualIt->expr;
    401420                        Type * actualType = actual->get_result();
     421
    402422                        PRINT(
    403423                                std::cerr << "formal type is ";
     
    408428                        )
    409429                        if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
     430                                // std::cerr << "unify failed" << std::endl;
    410431                                return false;
    411432                        }
     
    452473                        // match flattened actuals with formal parameters - actuals will be grouped to match
    453474                        // with formals as appropriate
    454                         Cost cost;
     475                        Cost cost = Cost::zero;
    455476                        std::list< Expression * > newExprs;
    456477                        ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
     
    613634                AssertionSet newNeed;
    614635                //AssertionParentSet needParents;
     636                PRINT(
     637                        std::cerr << "env is: " << std::endl;
     638                        newAlt.env.print( std::cerr, 0 );
     639                        std::cerr << std::endl;
     640                )
     641
    615642                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out );
    616643//      PRINT(
     
    643670                        makeExprList( instantiatedActuals, appExpr->get_args() );
    644671                        PRINT(
     672                                std::cerr << "instantiate function success: " << appExpr << std::endl;
    645673                                std::cerr << "need assertions:" << std::endl;
    646674                                printAssertionSet( resultNeed, std::cerr, 8 );
     
    663691                                UntypedExpr *vexpr = untypedExpr->clone();
    664692                                vexpr->set_result( pt.clone() );
    665                                 alternatives.push_back( Alternative( vexpr, env, Cost()) );
     693                                alternatives.push_back( Alternative( vexpr, env, Cost::zero) );
    666694                                return;
    667695                        }
     
    681709                AltList candidates;
    682710                SemanticError errors;
    683                 for ( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
     711                for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
    684712                        try {
    685713                                PRINT(
     
    688716                                )
    689717                                // check if the type is pointer to function
    690                                 PointerType *pointer;
    691                                 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) {
     718                                if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
    692719                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     720                                                referenceToRvalueConversion( func->expr );
    693721                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    694722                                                        // XXX
     
    696724                                                        makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    697725                                                }
    698                                         } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) {
    699                                                 EqvClass eqvClass;
    700                                                 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
    701                                                         if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
    702                                                                 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    703                                                                         makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
    704                                                                 } // for
    705                                                         } // if
     726                                        }
     727                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     728                                        referenceToRvalueConversion( func->expr );
     729                                        EqvClass eqvClass;
     730                                        if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
     731                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     732                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     733                                                                makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) );
     734                                                        } // for
    706735                                                } // if
    707736                                        } // if
     
    722751                                        }
    723752
    724                                         for ( AltList::const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
     753                                        for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
    725754                                                // check if the type is pointer to function
    726                                                 PointerType *pointer;
    727                                                 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) {
     755                                                if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
    728756                                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     757                                                                referenceToRvalueConversion( funcOp->expr );
    729758                                                                for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    730759                                                                        AltList currentAlt;
     
    753782                                PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    754783                                FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
    755                                 std::cerr << "Case +++++++++++++" << std::endl;
     784                                std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl;
    756785                                std::cerr << "formals are:" << std::endl;
    757786                                printAll( function->get_parameters(), std::cerr, 8 );
     
    796825        bool isLvalue( Expression *expr ) {
    797826                // xxx - recurse into tuples?
    798                 return expr->has_result() && expr->get_result()->get_lvalue();
     827                return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
    799828        }
    800829
     
    810839
    811840        Expression * restructureCast( Expression * argExpr, Type * toType ) {
    812                 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) {
    813                         // Argument expression is a tuple and the target type is not void. Cast each member of the tuple
    814                         // to its corresponding target type, producing the tuple of those cast expressions. If there are
    815                         // more components of the tuple than components in the target type, then excess components do not
    816                         // come out in the result expression (but UniqueExprs ensure that side effects will still be done).
    817                         if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
     841                if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) {
     842                        // Argument expression is a tuple and the target type is not void and not a reference type.
     843                        // Cast each member of the tuple to its corresponding target type, producing the tuple of those
     844                        // cast expressions. If there are more components of the tuple than components in the target type,
     845                        // then excess components do not come out in the result expression (but UniqueExprs ensure that
     846                        // side effects will still be done).
     847                        if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) {
    818848                                // expressions which may contain side effects require a single unique instance of the expression.
    819849                                argExpr = new UniqueExpr( argExpr );
     
    855885                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    856886                        // to.
    857                         int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
     887                        int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size();
    858888                        if ( discardedValues < 0 ) continue;
    859889                        // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    860890                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    861891                        // unification run for side-effects
    862                         unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
    863                         Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );
     892                        unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
     893                        Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env );
    864894                        if ( thisCost != Cost::infinity ) {
    865895                                // count one safe conversion for each value that is thrown away
    866                                 thisCost += Cost( 0, 0, discardedValues );
     896                                thisCost.incSafe( discardedValues );
    867897
    868898                                candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) );
     
    895925                funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
    896926                for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    897                         if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) {
    898                                 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    899                         } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) {
    900                                 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
    901                         } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) {
    902                                 addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
     927                        // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
     928                        std::unique_ptr<Expression> aggrExpr( agg->expr->clone() );
     929                        Type * aggrType = aggrExpr->get_result();
     930                        if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
     931                                aggrType = aggrType->stripReferences();
     932                                aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
     933                        }
     934                        // find member of the given type
     935                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
     936                                addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     937                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
     938                                addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     939                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
     940                                addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
    903941                        } // if
    904942                } // for
     
    915953                for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
    916954                        VariableExpr newExpr( *i, nameExpr->get_argName() );
    917                         alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     955                        alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    918956                        PRINT(
    919957                                std::cerr << "decl is ";
     
    941979        void AlternativeFinder::visit( SizeofExpr *sizeofExpr ) {
    942980                if ( sizeofExpr->get_isType() ) {
    943                         Type * newType = sizeofExpr->get_type()->clone();
    944                         alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     981                        // xxx - resolveTypeof?
     982                        alternatives.push_back( Alternative( sizeofExpr->clone(), env, Cost::zero ) );
    945983                } else {
    946984                        // find all alternatives for the argument to sizeof
     
    955993                        // return the lowest cost alternative for the argument
    956994                        Alternative &choice = winners.front();
     995                        referenceToRvalueConversion( choice.expr );
    957996                        alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    958997                } // if
     
    9611000        void AlternativeFinder::visit( AlignofExpr *alignofExpr ) {
    9621001                if ( alignofExpr->get_isType() ) {
    963                         Type * newType = alignofExpr->get_type()->clone();
    964                         alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1002                        // xxx - resolveTypeof?
     1003                        alternatives.push_back( Alternative( alignofExpr->clone(), env, Cost::zero ) );
    9651004                } else {
    9661005                        // find all alternatives for the argument to sizeof
     
    9751014                        // return the lowest cost alternative for the argument
    9761015                        Alternative &choice = winners.front();
     1016                        referenceToRvalueConversion( choice.expr );
    9771017                        alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    9781018                } // if
     
    10591099                        for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
    10601100                                VariableExpr newExpr( *i );
    1061                                 alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
     1101                                alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
    10621102                                renameTypes( alternatives.back().expr );
    10631103                        } // for
     
    12321272                                if ( thisCost != Cost::infinity ) {
    12331273                                        // count one safe conversion for each value that is thrown away
    1234                                         thisCost += Cost( 0, 0, discardedValues );
     1274                                        thisCost.incSafe( discardedValues );
    12351275                                        candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
    12361276                                }
Note: See TracChangeset for help on using the changeset viewer.