Changeset fb2bde4 for src/ResolvExpr


Ignore:
Timestamp:
Jun 24, 2019, 1:37:00 PM (5 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
08c0780
Parents:
3253c32
Message:

ConversionCost? has been ported to the new AST.

Location:
src/ResolvExpr
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/ConversionCost.cc

    r3253c32 rfb2bde4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 07:06:19 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon May  6 14:18:22 2019
    13 // Update Count     : 25
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 24 13:33:00 2019
     13// Update Count     : 26
    1414//
    1515
     
    489489        }
    490490
    491         Cost conversionCost(
    492                 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    493                 const ast::TypeEnvironment & env
    494         ) {
    495                 #warning unimplemented
    496                 (void)src; (void)dst; (void)symtab; (void)env;
    497                 assert(false);
     491static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
     492                const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
     493        return ptrsAssignable( t1, t2, env );
     494}
     495
     496// TODO: This is used for overload resolution. It might be able to be dropped once the old system
     497// is removed.
     498static Cost localConversionCost(
     499        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     500        const ast::TypeEnvironment & env
     501) { return conversionCost( src, dst, symtab, env ); }
     502
     503Cost conversionCost(
     504        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     505        const ast::TypeEnvironment & env
     506) {
     507        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     508                if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
     509                        if ( eqv->bound ) {
     510                                return conversionCost(src, eqv->bound, symtab, env );
     511                        } else {
     512                                return Cost::infinity;
     513                        }
     514                } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
     515                        const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
     516                        assertf( type, "Unexpected typedef." );
     517                        if ( type->base ) {
     518                                return conversionCost( src, type->base, symtab, env ) + Cost::safe;
     519                        }
     520                }
     521        }
     522        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
    498523                return Cost::zero;
    499         }
     524        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     525                return Cost::safe;
     526        } else if ( const ast::ReferenceType * refType =
     527                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
     528                return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
     529        } else {
     530                ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
     531                src->accept( converter );
     532                return converter.pass.cost;
     533        }
     534}
     535
     536Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, int diff,
     537                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     538                NumCostCalculation func ) {
     539        if ( 0 < diff ) {
     540                Cost cost = convertToReferenceCost(
     541                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
     542                        dst, (diff - 1), symtab, env, func );
     543                cost.incReference();
     544                return cost;
     545        } else if ( diff < -1 ) {
     546                Cost cost = convertToReferenceCost(
     547                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
     548                        (diff + 1), symtab, env, func );
     549                cost.incReference();
     550                return cost;
     551        } else if ( 0 == diff ) {
     552                const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
     553                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
     554                if ( srcAsRef && dstAsRef ) {
     555                        ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
     556                        ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
     557                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
     558                                        srcAsRef->base, dstAsRef->base, symtab, env ) ) {
     559                                if ( tq1 == tq2 ) {
     560                                        return Cost::zero;
     561                                } else {
     562                                        return Cost::safe;
     563                                }
     564                        } else {
     565                                int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
     566                                if ( 0 < assignResult ) {
     567                                        return Cost::safe;
     568                                } else if ( assignResult < 0 ) {
     569                                        return Cost::unsafe;
     570                                }
     571                        }
     572                } else {
     573                        ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
     574                        src->accept( converter );
     575                        return converter.pass.cost;
     576                }
     577        } else {
     578                assert( -1 == diff );
     579                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
     580                assert( dstAsRef );
     581                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
     582                        if ( src->is_lvalue() ) {
     583                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
     584                                        return Cost::reference;
     585                                } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
     586                                        return Cost::safe;
     587                                } else {
     588                                        return Cost::unsafe;
     589                                }
     590                        } else if ( dstAsRef->base->is_const() ) {
     591                                return Cost::safe;
     592                        } else {
     593                                return Cost::unsafe;
     594                        }
     595                }
     596        }
     597        return Cost::infinity;
     598}
     599
     600Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
     601            const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     602                NumCostCalculation func ) {
     603        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
     604        return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
     605}
     606
     607void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
     608        (void)voidType;
     609        cost = Cost::infinity;
     610}
     611
     612void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
     613        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
     614                int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
     615                if ( tableResult == -1 ) {
     616                        cost = Cost::unsafe;
     617                } else {
     618                        cost = Cost::zero;
     619                        cost.incSafe( tableResult );
     620                        cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
     621                }
     622        } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
     623                // xxx - not positive this is correct, but appears to allow casting int => enum
     624                cost = Cost::unsafe;
     625        }
     626}
     627
     628void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
     629        if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
     630                ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
     631                ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
     632                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
     633                                pointerType->base, dstAsPtr->base, symtab, env ) ) {
     634                        if ( tq1 == tq2 ) {
     635                                cost = Cost::zero;
     636                        } else {
     637                                cost = Cost::safe;
     638                        }
     639                } else {
     640                        int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
     641                        if ( 0 < assignResult && tq1 <= tq2 ) {
     642                                if ( tq1 == tq2 ) {
     643                                        cost = Cost::safe;
     644                                } else {
     645                                        cost = Cost::safe + Cost::safe;
     646                                }
     647                        } else if ( assignResult < 0 ) {
     648                                cost = Cost::unsafe;
     649                        } // else Cost::infinity
     650                }
     651        }
     652}
     653
     654void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
     655        (void)arrayType;
     656}
     657
     658void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
     659        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
     660
     661        cost = costCalc( refType->base, dst, symtab, env );
     662        if ( refType->base->qualifiers == dst->qualifiers ) {
     663                cost.incReference();
     664        } else if ( refType->base->qualifiers < dst->qualifiers ) {
     665                cost.incSafe();
     666        } else {
     667                cost.incUnsafe();
     668        }
     669}
     670
     671void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
     672        (void)functionType;
     673}
     674
     675void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {
     676        if ( const ast::StructInstType * dstAsInst =
     677                        dynamic_cast< const ast::StructInstType * >( dst ) ) {
     678                if ( structInstType->name == dstAsInst->name ) {
     679                        cost = Cost::zero;
     680                }
     681        }
     682}
     683
     684void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {
     685        if ( const ast::UnionInstType * dstAsInst =
     686                        dynamic_cast< const ast::UnionInstType * >( dst ) ) {
     687                if ( unionInstType->name == dstAsInst->name ) {
     688                        cost = Cost::zero;
     689                }
     690        }
     691}
     692
     693void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
     694        (void)enumInstType;
     695        static const ast::BasicType integer( ast::BasicType::SignedInt );
     696        cost = costCalc( &integer, dst, symtab, env );
     697        if ( cost < Cost::unsafe ) {
     698                cost.incSafe();
     699        }
     700}
     701
     702void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
     703        (void)traitInstType;
     704}
     705
     706void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
     707        if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
     708                cost = costCalc( eqv->bound, dst, symtab, env );
     709        } else if ( const ast::TypeInstType * dstAsInst =
     710                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     711                if ( typeInstType->name == dstAsInst->name ) {
     712                        cost = Cost::zero;
     713                }
     714        } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
     715                const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
     716                assertf( type, "Unexpected typedef.");
     717                if ( type->base ) {
     718                        cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
     719                }
     720        }
     721}
     722
     723void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
     724        Cost c = Cost::zero;
     725        if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
     726                auto srcIt = tupleType->types.begin();
     727                auto dstIt = dstAsTuple->types.begin();
     728                auto srcEnd = tupleType->types.end();
     729                auto dstEnd = dstAsTuple->types.end();
     730                while ( srcIt != srcEnd && dstIt != dstEnd ) {
     731                        Cost newCost = costCalc( *srcIt++, *dstIt++, symtab, env );
     732                        if ( newCost == Cost::infinity ) {
     733                                return;
     734                        }
     735                        c += newCost;
     736                }
     737                if ( dstIt != dstEnd ) {
     738                        cost = Cost::infinity;
     739                } else {
     740                        cost = c;
     741                }
     742        }
     743}
     744
     745void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
     746        (void)varArgsType;
     747        if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
     748                cost = Cost::zero;
     749        }
     750}
     751
     752void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
     753        (void)zeroType;
     754        if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
     755                cost = Cost::zero;
     756        } else if ( const ast::BasicType * dstAsBasic =
     757                        dynamic_cast< const ast::BasicType * >( dst ) ) {
     758                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
     759                if ( -1 == tableResult ) {
     760                        cost = Cost::unsafe;
     761                } else {
     762                        cost = Cost::zero;
     763                        cost.incSafe( tableResult + 1 );
     764                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
     765                }
     766        }
     767}
     768
     769void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
     770        (void)oneType;
     771        if ( dynamic_cast< const ast::OneType * >( dst ) ) {
     772                cost = Cost::zero;
     773        } else if ( const ast::BasicType * dstAsBasic =
     774                        dynamic_cast< const ast::BasicType * >( dst ) ) {
     775                int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
     776                if ( -1 == tableResult ) {
     777                        cost = Cost::unsafe;
     778                } else {
     779                        cost = Cost::zero;
     780                        cost.incSafe( tableResult + 1 );
     781                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
     782                }
     783        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
     784                cost = Cost::zero;
     785                cost.incSafe( maxIntCost + 2 );
     786        }
     787}
     788
     789
    500790} // namespace ResolvExpr
    501791
  • src/ResolvExpr/ConversionCost.h

    r3253c32 rfb2bde4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:37:28 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:38:24 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 24 10:00:00 2019
     13// Update Count     : 5
    1414//
    1515
     
    2020#include "Cost.h"             // for Cost
    2121
     22#include "AST/Fwd.hpp"
     23#include "AST/Pass.hpp"       // for WithShortCircuiting
    2224#include "Common/PassVisitor.h"
    2325#include "SynTree/Visitor.h"  // for Visitor
     
    6567        typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
    6668        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
     69
     70// Some function pointer types, differ in return type.
     71using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
     72        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
     73using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *,
     74        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
     75
     76// TODO: When the old ConversionCost is removed, get ride of the _new suffix.
     77class ConversionCost_new : public ast::WithShortCircuiting {
     78        const ast::Type * dst;
     79        const ast::SymbolTable & symtab;
     80        const ast::TypeEnvironment & env;
     81        CostCalculation costCalc;
     82public:
     83        Cost cost;
     84
     85        ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,
     86                        const ast::TypeEnvironment & env, CostCalculation costCalc ) :
     87                dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity )
     88        {}
     89
     90        void previsit( const ast::Node * ) { visit_children = false; }
     91
     92        void postvisit( const ast::VoidType * voidType );
     93        void postvisit( const ast::BasicType * basicType );
     94        void postvisit( const ast::PointerType * pointerType );
     95        void postvisit( const ast::ArrayType * arrayType );
     96        void postvisit( const ast::ReferenceType * refType );
     97        void postvisit( const ast::FunctionType * functionType );
     98        void postvisit( const ast::StructInstType * structInstType );
     99        void postvisit( const ast::UnionInstType * unionInstType );
     100        void postvisit( const ast::EnumInstType * enumInstType );
     101        void postvisit( const ast::TraitInstType * traitInstType );
     102        void postvisit( const ast::TypeInstType * typeInstType );
     103        void postvisit( const ast::TupleType * tupleType );
     104        void postvisit( const ast::VarArgsType * varArgsType );
     105        void postvisit( const ast::ZeroType * zeroType );
     106        void postvisit( const ast::OneType * oneType );
     107};
     108
     109Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
     110        const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
     111
    67112} // namespace ResolvExpr
    68113
  • src/ResolvExpr/PtrsAssignable.cc

    r3253c32 rfb2bde4  
    1414//
    1515
     16#include "AST/Fwd.hpp"
    1617#include "Common/PassVisitor.h"
    1718#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     
    107108        void PtrsAssignable::postvisit(  __attribute__((unused)) OneType *oneType ) {}
    108109
     110int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
     111                const ast::TypeEnvironment & env ) {
     112        #warning unimplemented
     113        (void)src;
     114        (void)dst;
     115        (void)env;
     116        assert(0);
     117        return 0;
     118}
     119
    109120} // namespace ResolvExpr
    110121
  • src/ResolvExpr/typeops.h

    r3253c32 rfb2bde4  
    9494        // in PtrsAssignable.cc
    9595        int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env );
     96        int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
     97                const ast::TypeEnvironment & env );
    9698
    9799        // in PtrsCastable.cc
Note: See TracChangeset for help on using the changeset viewer.