Changeset 800d275 for src/ResolvExpr


Ignore:
Timestamp:
Aug 29, 2017, 2:54:49 PM (8 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, stuck-waitfor-destruct, with_gc
Children:
235b41f
Parents:
28e58fd (diff), 6454949 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src/ResolvExpr
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r28e58fd r800d275  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:52:08 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jul 26 11:33:00 2017
    13 // Update Count     : 31
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Aug 28 13:47:24 2017
     13// Update Count     : 32
    1414//
    1515
     
    195195                                AltList winners;
    196196                                findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );
    197                                 stream << "Can't choose between " << winners.size() << " alternatives for expression ";
     197                                stream << "Cannot choose between " << winners.size() << " alternatives for expression ";
    198198                                expr->print( stream );
    199199                                stream << "Alternatives are:";
     
    286286        }
    287287
    288         Cost computeConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
     288        Cost computeConversionCost( Type * actualType, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
     289                PRINT(
     290                        std::cerr << std::endl << "converting ";
     291                        actualType->print( std::cerr, 8 );
     292                        std::cerr << std::endl << " to ";
     293                        formalType->print( std::cerr, 8 );
     294                        std::cerr << std::endl << "environment is: ";
     295                        env.print( std::cerr, 8 );
     296                        std::cerr << std::endl;
     297                )
     298                Cost convCost = conversionCost( actualType, formalType, indexer, env );
     299                PRINT(
     300                        std::cerr << std::endl << "cost is" << convCost << std::endl;
     301                )
     302                if ( convCost == Cost::infinity ) {
     303                        return convCost;
     304                }
     305                convCost.incPoly( polyCost( formalType, env, indexer ) + polyCost( actualType, env, indexer ) );
     306                return convCost;
     307        }
     308
     309        Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
     310                Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env );
     311                // if ( convCost != Cost::zero ) {
     312
     313                // xxx - temporary -- ignore poly cost, since this causes some polymorphic functions to be cast, which causes the specialize
     314                // pass to try to specialize them, which currently does not work. Once that is fixed, remove the next 3 lines and uncomment the
     315                // previous line.
     316                Cost tmpCost = convCost;
     317                tmpCost.incPoly( -tmpCost.get_polyCost() );
     318                if ( tmpCost != Cost::zero ) {
     319                        Type *newType = formalType->clone();
     320                        env.apply( newType );
     321                        actualExpr = new CastExpr( actualExpr, newType );
     322                        // xxx - SHOULD be able to resolve this cast, but at the moment pointers are not castable to zero_t, but are implicitly convertible. This is clearly
     323                        // inconsistent, once this is fixed it should be possible to resolve the cast.
     324                        // xxx - this isn't working, it appears because type1 (the formal type) is seen as widenable, but it shouldn't be, because this makes the conversion from DT* to DT* since commontype(zero_t, DT*) is DT*, rather than just nothing.
     325
     326                        // AlternativeFinder finder( indexer, env );
     327                        // finder.findWithAdjustment( actualExpr );
     328                        // assertf( finder.get_alternatives().size() > 0, "Somehow castable expression failed to find alternatives." );
     329                        // assertf( finder.get_alternatives().size() == 1, "Somehow got multiple alternatives for known cast expression." );
     330                        // Alternative & alt = finder.get_alternatives().front();
     331                        // delete actualExpr;
     332                        // actualExpr = alt.expr->clone();
     333                }
     334                return convCost;
     335        }
     336
     337        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    289338                ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( alt.expr );
    290339                PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
     
    304353                                actualType->print( std::cerr, 8 );
    305354                        )
    306                         Cost actualCost = Cost::zero;
    307355                        if ( formal == formals.end() ) {
    308356                                if ( function->get_isVarArgs() ) {
     
    325373                                std::cerr << std::endl;
    326374                        )
    327                         Cost newCost = conversionCost( actualType, formalType, indexer, alt.env );
    328                         PRINT(
    329                                 std::cerr << std::endl << "cost is" << newCost << std::endl;
    330                         )
    331 
    332                         if ( newCost == Cost::infinity ) {
    333                                 return newCost;
    334                         }
    335                         convCost += newCost;
    336                         actualCost += newCost;
    337                         if ( actualCost != Cost::zero ) {
    338                                 Type *newType = formalType->clone();
    339                                 alt.env.apply( newType );
    340                                 *actualExpr = new CastExpr( *actualExpr, newType );
    341                         }
    342                         convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) );
     375                        convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
    343376                        ++formal; // can't be in for-loop update because of the continue
    344377                }
     
    348381
    349382                for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
    350                         PRINT(
    351                                 std::cerr << std::endl << "converting ";
    352                                 assert->second.actualType->print( std::cerr, 8 );
    353                                 std::cerr << std::endl << " to ";
    354                                 assert->second.formalType->print( std::cerr, 8 );
    355                         )
    356                         Cost newCost = conversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
    357                         PRINT(
    358                                 std::cerr << std::endl << "cost of conversion is " << newCost << std::endl;
    359                         )
    360                         if ( newCost == Cost::infinity ) {
    361                                 return newCost;
    362                         }
    363                         convCost += newCost;
    364                         convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) );
     383                        convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
    365384                }
    366385
     
    679698
    680699        void AlternativeFinder::visit( UntypedExpr *untypedExpr ) {
    681                 bool doneInit = false;
    682                 AlternativeFinder funcOpFinder( indexer, env );
    683 
    684                 AlternativeFinder funcFinder( indexer, env );
    685 
    686700                {
    687701                        std::string fname = InitTweak::getFunctionName( untypedExpr );
     
    696710                }
    697711
     712                AlternativeFinder funcFinder( indexer, env );
    698713                funcFinder.findWithAdjustment( untypedExpr->get_function() );
     714                // if there are no function alternatives, then proceeding is a waste of time.
     715                if ( funcFinder.alternatives.empty() ) return;
     716
    699717                std::list< AlternativeFinder > argAlternatives;
    700718                findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), back_inserter( argAlternatives ) );
     
    706724                // if not tuple assignment, assignment is taken care of as a normal function call
    707725                Tuples::handleTupleAssignment( *this, untypedExpr, possibilities );
     726
     727                // find function operators
     728                AlternativeFinder funcOpFinder( indexer, env );
     729                NameExpr *opExpr = new NameExpr( "?()" );
     730                try {
     731                        funcOpFinder.findWithAdjustment( opExpr );
     732                } catch( SemanticError &e ) {
     733                        // it's ok if there aren't any defined function ops
     734                }
     735                PRINT(
     736                        std::cerr << "known function ops:" << std::endl;
     737                        printAlts( funcOpFinder.alternatives, std::cerr, 8 );
     738                )
    708739
    709740                AltList candidates;
     
    735766                                                } // if
    736767                                        } // if
    737                                 } else {
    738                                         // seek a function operator that's compatible
    739                                         if ( ! doneInit ) {
    740                                                 doneInit = true;
    741                                                 NameExpr *opExpr = new NameExpr( "?()" );
    742                                                 try {
    743                                                         funcOpFinder.findWithAdjustment( opExpr );
    744                                                 } catch( SemanticError &e ) {
    745                                                         // it's ok if there aren't any defined function ops
    746                                                 }
    747                                                 PRINT(
    748                                                         std::cerr << "known function ops:" << std::endl;
    749                                                         printAlts( funcOpFinder.alternatives, std::cerr, 8 );
    750                                                 )
    751                                         }
    752 
    753                                         for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
    754                                                 // check if the type is pointer to function
    755                                                 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
    756                                                         if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
    757                                                                 referenceToRvalueConversion( funcOp->expr );
    758                                                                 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
    759                                                                         AltList currentAlt;
    760                                                                         currentAlt.push_back( *func );
    761                                                                         currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
    762                                                                         makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
    763                                                                 } // for
    764                                                         } // if
     768                                }
     769
     770                                // try each function operator ?() with the current function alternative and each of the argument combinations
     771                                for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {
     772                                        // check if the type is pointer to function
     773                                        if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) {
     774                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     775                                                        referenceToRvalueConversion( funcOp->expr );
     776                                                        for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
     777                                                                AltList currentAlt;
     778                                                                currentAlt.push_back( *func );
     779                                                                currentAlt.insert( currentAlt.end(), actualAlt->begin(), actualAlt->end() );
     780                                                                makeFunctionAlternatives( *funcOp, function, currentAlt, std::back_inserter( candidates ) );
     781                                                        } // for
    765782                                                } // if
    766                                         } // for
    767                                 } // if
     783                                        } // if
     784                                } // for
    768785                        } catch ( SemanticError &e ) {
    769786                                errors.append( e );
     
    776793                // compute conversionsion costs
    777794                for ( AltList::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc ) {
    778                         Cost cvtCost = computeConversionCost( *withFunc, indexer );
     795                        Cost cvtCost = computeApplicationConversionCost( *withFunc, indexer );
    779796
    780797                        PRINT(
     
    895912                                // count one safe conversion for each value that is thrown away
    896913                                thisCost.incSafe( discardedValues );
    897 
    898                                 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) );
     914                                Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost );
     915                                // xxx - this doesn't work at the moment, since inferParameters requires an ApplicationExpr as the alternative.
     916                                // Once this works, it should be possible to infer parameters on a cast expression and specialize any function.
     917
     918                                // inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
     919                                candidates.emplace_back( std::move( newAlt ) );
    899920                        } // if
    900921                } // for
     
    11391160                                                ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
    11401161                                                newExpr->set_result( commonType ? commonType : second->expr->get_result()->clone() );
     1162                                                // convert both options to the conditional result type
     1163                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
     1164                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env );
    11411165                                                newAlt.expr = newExpr;
    11421166                                                inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
  • src/ResolvExpr/CastCost.cc

    r28e58fd r800d275  
    5858                        return Cost::safe;
    5959                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    60                         return convertToReferenceCost( src, refType, indexer, env );
     60                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {
     61                                return ptrsCastable( t1, t2, env, indexer );
     62                        });
    6163                } else {
    6264                        CastCost converter( dest, indexer, env );
  • src/ResolvExpr/ConversionCost.cc

    r28e58fd r800d275  
    4040#define PRINT(x)
    4141#endif
    42 
    4342        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    4443                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
     
    7877                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    7978                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    80                         return convertToReferenceCost( src, refType, indexer, env );
     79                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){
     80                                return ptrsAssignable( t1, t2, env );
     81                        });
    8182                } else {
    8283                        ConversionCost converter( dest, indexer, env );
     
    9091        }
    9192
    92         Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     93        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    9394                PRINT( std::cerr << "convert to reference cost..." << std::endl; )
    9495                if ( diff > 0 ) {
    9596                        // TODO: document this
    96                         Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env );
     97                        Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env, func );
    9798                        cost.incReference();
    9899                        return cost;
    99100                } else if ( diff < -1 ) {
    100101                        // TODO: document this
    101                         Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env );
     102                        Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env, func );
    102103                        cost.incReference();
    103104                        return cost;
     
    110111                                        return Cost::safe;
    111112                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    112                                         int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env );
     113                                        int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer );
    113114                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
    114115                                        if ( assignResult < 0 ) {
     
    157158        }
    158159
    159         Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     160        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    160161                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
    161                 return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env );
     162                return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env, func );
    162163        }
    163164
  • src/ResolvExpr/ConversionCost.h

    r28e58fd r800d275  
    1616#pragma once
    1717
     18#include <functional>         // for function
     19
    1820#include "Cost.h"             // for Cost
    1921#include "SynTree/Visitor.h"  // for Visitor
     
    2123
    2224namespace SymTab {
    23 class Indexer;
     25        class Indexer;
    2426}  // namespace SymTab
    2527
    2628namespace ResolvExpr {
    27 class TypeEnvironment;
     29        class TypeEnvironment;
    2830
    2931        class ConversionCost : public Visitor {
     
    5557        };
    5658
    57         Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env );
     59        typedef std::function<int(Type *, Type *, const TypeEnvironment &, const SymTab::Indexer &)> PtrsFunction;
     60        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
    5861} // namespace ResolvExpr
    5962
  • src/ResolvExpr/Cost.h

    r28e58fd r800d275  
    2828                Cost & incSafe( int inc = 1 );
    2929                Cost & incReference( int inc = 1 );
     30
     31                int get_unsafeCost() const { return unsafeCost; }
     32                int get_polyCost() const { return polyCost; }
     33                int get_safeCost() const { return safeCost; }
     34                int get_referenceCost() const { return referenceCost; }
    3035
    3136                Cost operator+( const Cost &other ) const;
Note: See TracChangeset for help on using the changeset viewer.