[51b7345] | 1 | #include "typeops.h" |
---|
| 2 | #include "Cost.h" |
---|
| 3 | #include "ConversionCost.h" |
---|
| 4 | #include "SynTree/Type.h" |
---|
| 5 | #include "SynTree/Visitor.h" |
---|
| 6 | #include "SymTab/Indexer.h" |
---|
| 7 | |
---|
| 8 | |
---|
| 9 | namespace ResolvExpr { |
---|
[c11e31c] | 10 | class CastCost : public ConversionCost { |
---|
| 11 | public: |
---|
| 12 | CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); |
---|
[51b7345] | 13 | |
---|
[c11e31c] | 14 | virtual void visit( BasicType *basicType ); |
---|
| 15 | virtual void visit( PointerType *pointerType ); |
---|
| 16 | }; |
---|
[51b7345] | 17 | |
---|
[c11e31c] | 18 | Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { |
---|
| 19 | if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) { |
---|
| 20 | EqvClass eqvClass; |
---|
| 21 | NamedTypeDecl *namedType; |
---|
| 22 | if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { |
---|
| 23 | return castCost( src, eqvClass.type, indexer, env ); |
---|
| 24 | } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) { |
---|
| 25 | TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); |
---|
| 26 | // all typedefs should be gone by this point |
---|
| 27 | assert( type ); |
---|
| 28 | if ( type->get_base() ) { |
---|
| 29 | return castCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 ); |
---|
| 30 | } // if |
---|
| 31 | } // if |
---|
| 32 | } // if |
---|
| 33 | if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { |
---|
| 34 | return Cost( 0, 0, 0 ); |
---|
| 35 | } else if ( dynamic_cast< VoidType* >( dest ) ) { |
---|
| 36 | return Cost( 0, 0, 1 ); |
---|
| 37 | } else { |
---|
| 38 | CastCost converter( dest, indexer, env ); |
---|
| 39 | src->accept( converter ); |
---|
| 40 | if ( converter.get_cost() == Cost::infinity ) { |
---|
| 41 | return Cost::infinity; |
---|
| 42 | } else { |
---|
| 43 | return converter.get_cost() + Cost( 0, 0, 0 ); |
---|
| 44 | } // if |
---|
| 45 | } // if |
---|
[51b7345] | 46 | } |
---|
| 47 | |
---|
[c11e31c] | 48 | CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) |
---|
| 49 | : ConversionCost( dest, indexer, env ) { |
---|
| 50 | } |
---|
[51b7345] | 51 | |
---|
[c11e31c] | 52 | void CastCost::visit( BasicType *basicType ) { |
---|
| 53 | if ( dynamic_cast< PointerType* >( dest ) ) { |
---|
| 54 | cost = Cost( 1, 0, 0 ); |
---|
| 55 | } else { |
---|
| 56 | ConversionCost::visit( basicType ); |
---|
| 57 | } // if |
---|
[51b7345] | 58 | } |
---|
| 59 | |
---|
[c11e31c] | 60 | void CastCost::visit( PointerType *pointerType ) { |
---|
| 61 | if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { |
---|
| 62 | if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { |
---|
| 63 | cost = Cost( 0, 0, 1 ); |
---|
| 64 | } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { |
---|
| 65 | if ( destAsBasic->isInteger() ) { |
---|
| 66 | cost = Cost( 1, 0, 0 ); |
---|
| 67 | } |
---|
| 68 | } else { |
---|
| 69 | TypeEnvironment newEnv( env ); |
---|
| 70 | newEnv.add( pointerType->get_forall() ); |
---|
| 71 | newEnv.add( pointerType->get_base()->get_forall() ); |
---|
| 72 | int assignResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer ); |
---|
| 73 | if ( assignResult > 0 ) { |
---|
| 74 | cost = Cost( 0, 0, 1 ); |
---|
| 75 | } else if ( assignResult < 0 ) { |
---|
| 76 | cost = Cost( 1, 0, 0 ); |
---|
| 77 | } // if |
---|
| 78 | } // if |
---|
| 79 | } // if |
---|
| 80 | } |
---|
[51b7345] | 81 | } // namespace ResolvExpr |
---|