Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/ConversionCost.cc

    rbd0b6b62 rb0837e4  
    4444                        EqvClass eqvClass;
    4545                        NamedTypeDecl *namedType;
    46                         PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
    47                         if ( env.lookup( destAsTypeInst->name, eqvClass ) ) {
     46                        PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); )
     47                        if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
    4848                                if ( eqvClass.type ) {
    4949                                        return conversionCost( src, eqvClass.type, indexer, env );
     
    5151                                        return Cost::infinity;
    5252                                }
    53                         } else if ( ( namedType = indexer.lookupType( destAsTypeInst->name ) ) ) {
     53                        } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
    5454                                PRINT( std::cerr << " found" << std::endl; )
    5555                                TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    5656                                // all typedefs should be gone by this point
    5757                                assert( type );
    58                                 if ( type->base ) {
    59                                         return conversionCost( src, type->base, indexer, env ) + Cost::safe;
     58                                if ( type->get_base() ) {
     59                                        return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
    6060                                } // if
    6161                        } // if
     
    7777                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    7878                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    79                         return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
     79                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){
    8080                                return ptrsAssignable( t1, t2, env );
    8181                        });
    8282                } else {
    83                         PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
     83                        ConversionCost converter( dest, indexer, env );
    8484                        src->accept( converter );
    85                         if ( converter.pass.get_cost() == Cost::infinity ) {
     85                        if ( converter.get_cost() == Cost::infinity ) {
    8686                                return Cost::infinity;
    8787                        } else {
    88                                 return converter.pass.get_cost() + Cost::zero;
     88                                return converter.get_cost() + Cost::zero;
    8989                        } // if
    9090                } // if
     
    9292
    9393        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    94                 PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
     94                PRINT( std::cerr << "convert to reference cost... diff " << diff << std::endl; )
    9595                if ( diff > 0 ) {
    9696                        // TODO: document this
    97                         Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func );
     97                        Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env, func );
    9898                        cost.incReference();
    9999                        return cost;
    100100                } else if ( diff < -1 ) {
    101101                        // TODO: document this
    102                         Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func );
     102                        Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env, func );
    103103                        cost.incReference();
    104104                        return cost;
     
    108108                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
    109109                                PRINT( std::cerr << "converting between references" << std::endl; )
    110                                 Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers();
    111                                 Type::Qualifiers tq2 = destAsRef->base->get_qualifiers();
    112                                 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
    113                                         PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    114                                         if ( tq1 == tq2 ) {
    115                                                 // types are the same
    116                                                 return Cost::zero;
    117                                         } else {
    118                                                 // types are the same, except otherPointer has more qualifiers
    119                                                 return Cost::safe;
    120                                         }
     110                                if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
     111                                        return Cost::safe;
    121112                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    122                                         int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
     113                                        int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer );
    123114                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
    124115                                        if ( assignResult > 0 ) {
     
    130121                        } else {
    131122                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
    132                                 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
     123                                ConversionCost converter( dest, indexer, env );
    133124                                src->accept( converter );
    134                                 return converter.pass.get_cost();
     125                                return converter.get_cost();
    135126                        } // if
    136127                } else {
     
    138129                        assert( diff == -1 && destAsRef );
    139130                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    140                         if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
     131                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
    141132                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
    142133                                if ( src->get_lvalue() ) {
     
    146137                                        )
    147138                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
    148                                         if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) {
     139                                        if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
    149140                                                return Cost::reference; // cost needs to be non-zero to add cast
    150                                         } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) {
     141                                        } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
    151142                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
    152143                                        } else {
    153144                                                return Cost::unsafe;
    154145                                        } // if
    155                                 } else if ( destAsRef->base->get_const() ) {
     146                                } else if ( destAsRef->get_base()->get_const() ) {
    156147                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
    157148                                        // rvalue-to-const-reference conversion: T => const T &
     
    173164        }
    174165
    175         ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    176                 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
     166        ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )
     167                : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {
    177168        }
    178169
     
    257248        };
    258249
    259         void ConversionCost::postvisit( VoidType * ) {
     250        void ConversionCost::visit( __attribute((unused)) VoidType *voidType ) {
    260251                cost = Cost::infinity;
    261252        }
    262253
    263         void ConversionCost::postvisit(BasicType *basicType) {
     254        void ConversionCost::visit(BasicType *basicType) {
    264255                if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
    265256                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
     
    278269        }
    279270
    280         void ConversionCost::postvisit( PointerType * pointerType ) {
     271        void ConversionCost::visit( PointerType * pointerType ) {
    281272                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    282                         PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
    283                         Type::Qualifiers tq1 = pointerType->base->get_qualifiers();
    284                         Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers();
    285                         if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    286                                 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     273                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr; )
     274                        Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
     275                        Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
     276                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
    287277                                if ( tq1 == tq2 ) {
    288278                                        // types are the same
     
    290280                                } else {
    291281                                        // types are the same, except otherPointer has more qualifiers
     282                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    292283                                        cost = Cost::safe;
    293284                                }
    294                         } else {
     285                        } else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    295286                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
    296287                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
    297                                 if ( assignResult > 0 && tq1 <= tq2 ) {
    298                                         // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct?
    299                                         if ( tq1 == tq2 ) {
    300                                                 cost = Cost::safe;
    301                                         } else if ( tq1 < tq2 ) {
    302                                                 cost = Cost::safe+Cost::safe;
    303                                         }
     288                                if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
     289                                        cost = Cost::safe;
    304290                                } else if ( assignResult < 0 ) {
    305291                                        cost = Cost::unsafe;
     
    312298        }
    313299
    314         void ConversionCost::postvisit( ArrayType * ) {}
    315 
    316         void ConversionCost::postvisit( ReferenceType * refType ) {
     300        void ConversionCost::visit( ArrayType * ) {}
     301
     302        void ConversionCost::visit( ReferenceType * refType ) {
    317303                // Note: dest can never be a reference, since it would have been caught in an earlier check
    318304                assert( ! dynamic_cast< ReferenceType * >( dest ) );
     
    320306                // recursively compute conversion cost from T1 to T2.
    321307                // cv can be safely dropped because of 'implicit dereference' behavior.
    322                 cost = costFunc( refType->base, dest, indexer, env );
     308                refType->base->accept( *this );
    323309                if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
    324310                        cost.incReference();  // prefer exact qualifiers
     
    331317        }
    332318
    333         void ConversionCost::postvisit( FunctionType * ) {}
    334 
    335         void ConversionCost::postvisit( StructInstType * inst ) {
     319        void ConversionCost::visit( FunctionType * ) {}
     320
     321        void ConversionCost::visit( StructInstType * inst ) {
    336322                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
    337323                        if ( inst->name == destAsInst->name ) {
     
    341327        }
    342328
    343         void ConversionCost::postvisit( UnionInstType * inst ) {
     329        void ConversionCost::visit( UnionInstType * inst ) {
    344330                if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
    345331                        if ( inst->name == destAsInst->name ) {
     
    349335        }
    350336
    351         void ConversionCost::postvisit( EnumInstType * ) {
     337        void ConversionCost::visit( EnumInstType * ) {
    352338                static Type::Qualifiers q;
    353339                static BasicType integer( q, BasicType::SignedInt );
    354                 cost = costFunc( &integer, dest, indexer, env );  // safe if dest >= int
     340                integer.accept( *this );  // safe if dest >= int
    355341                if ( cost < Cost::unsafe ) {
    356342                        cost.incSafe();
     
    358344        }
    359345
    360         void ConversionCost::postvisit( TraitInstType * ) {}
    361 
    362         void ConversionCost::postvisit( TypeInstType *inst ) {
     346        void ConversionCost::visit( TraitInstType * ) {}
     347
     348        void ConversionCost::visit( TypeInstType *inst ) {
    363349                EqvClass eqvClass;
    364350                NamedTypeDecl *namedType;
    365                 if ( env.lookup( inst->name, eqvClass ) ) {
    366                         cost = costFunc( eqvClass.type, dest, indexer, env );
     351                if ( env.lookup( inst->get_name(), eqvClass ) ) {
     352                        cost = conversionCost( eqvClass.type, dest, indexer, env );
    367353                } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
    368                         if ( inst->name == destAsInst->name ) {
     354                        if ( inst->get_name() == destAsInst->get_name() ) {
    369355                                cost = Cost::zero;
    370356                        }
    371                 } else if ( ( namedType = indexer.lookupType( inst->name ) ) ) {
     357                } else if ( ( namedType = indexer.lookupType( inst->get_name() ) ) ) {
    372358                        TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    373359                        // all typedefs should be gone by this point
    374360                        assert( type );
    375                         if ( type->base ) {
    376                                 cost = costFunc( type->base, dest, indexer, env ) + Cost::safe;
    377                         } // if
    378                 } // if
    379         }
    380 
    381         void ConversionCost::postvisit( TupleType * tupleType ) {
     361                        if ( type->get_base() ) {
     362                                cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
     363                        } // if
     364                } // if
     365        }
     366
     367        void ConversionCost::visit( TupleType * tupleType ) {
    382368                Cost c = Cost::zero;
    383369                if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
    384                         std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
    385                         std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
    386                         while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
    387                                 Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env );
     370                        std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin();
     371                        std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin();
     372                        while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) {
     373                                Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env );
    388374                                if ( newCost == Cost::infinity ) {
    389375                                        return;
     
    391377                                c += newCost;
    392378                        } // while
    393                         if ( destIt != destAsTuple->types.end() ) {
     379                        if ( destIt != destAsTuple->get_types().end() ) {
    394380                                cost = Cost::infinity;
    395381                        } else {
     
    399385        }
    400386
    401         void ConversionCost::postvisit( VarArgsType * ) {
     387        void ConversionCost::visit( VarArgsType * ) {
    402388                if ( dynamic_cast< VarArgsType* >( dest ) ) {
    403389                        cost = Cost::zero;
     
    405391        }
    406392
    407         void ConversionCost::postvisit( ZeroType * ) {
     393        void ConversionCost::visit( ZeroType * ) {
    408394                if ( dynamic_cast< ZeroType * >( dest ) ) {
    409395                        cost = Cost::zero;
     
    422408        }
    423409
    424         void ConversionCost::postvisit( OneType * ) {
     410        void ConversionCost::visit( OneType * ) {
    425411                if ( dynamic_cast< OneType * >( dest ) ) {
    426412                        cost = Cost::zero;
Note: See TracChangeset for help on using the changeset viewer.