Changeset 800d275 for src/ResolvExpr
- Timestamp:
- Aug 29, 2017, 2:54:49 PM (8 years ago)
- 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. - Location:
- src/ResolvExpr
- Files:
-
- 5 edited
-
AlternativeFinder.cc (modified) (13 diffs)
-
CastCost.cc (modified) (1 diff)
-
ConversionCost.cc (modified) (5 diffs)
-
ConversionCost.h (modified) (3 diffs)
-
Cost.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r28e58fd r800d275 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:52:08 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Jul 26 11:33:00201713 // Update Count : 3 111 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 28 13:47:24 2017 13 // Update Count : 32 14 14 // 15 15 … … 195 195 AltList winners; 196 196 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 "; 198 198 expr->print( stream ); 199 199 stream << "Alternatives are:"; … … 286 286 } 287 287 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 ) { 289 338 ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( alt.expr ); 290 339 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); … … 304 353 actualType->print( std::cerr, 8 ); 305 354 ) 306 Cost actualCost = Cost::zero;307 355 if ( formal == formals.end() ) { 308 356 if ( function->get_isVarArgs() ) { … … 325 373 std::cerr << std::endl; 326 374 ) 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 ); 343 376 ++formal; // can't be in for-loop update because of the continue 344 377 } … … 348 381 349 382 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 ); 365 384 } 366 385 … … 679 698 680 699 void AlternativeFinder::visit( UntypedExpr *untypedExpr ) { 681 bool doneInit = false;682 AlternativeFinder funcOpFinder( indexer, env );683 684 AlternativeFinder funcFinder( indexer, env );685 686 700 { 687 701 std::string fname = InitTweak::getFunctionName( untypedExpr ); … … 696 710 } 697 711 712 AlternativeFinder funcFinder( indexer, env ); 698 713 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 699 717 std::list< AlternativeFinder > argAlternatives; 700 718 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), back_inserter( argAlternatives ) ); … … 706 724 // if not tuple assignment, assignment is taken care of as a normal function call 707 725 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 ) 708 739 709 740 AltList candidates; … … 735 766 } // if 736 767 } // 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 765 782 } // if 766 } // for767 } // if783 } // if 784 } // for 768 785 } catch ( SemanticError &e ) { 769 786 errors.append( e ); … … 776 793 // compute conversionsion costs 777 794 for ( AltList::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc ) { 778 Cost cvtCost = compute ConversionCost( *withFunc, indexer );795 Cost cvtCost = computeApplicationConversionCost( *withFunc, indexer ); 779 796 780 797 PRINT( … … 895 912 // count one safe conversion for each value that is thrown away 896 913 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 ) ); 899 920 } // if 900 921 } // for … … 1139 1160 ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() ); 1140 1161 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 ); 1141 1165 newAlt.expr = newExpr; 1142 1166 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); -
src/ResolvExpr/CastCost.cc
r28e58fd r800d275 58 58 return Cost::safe; 59 59 } 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 }); 61 63 } else { 62 64 CastCost converter( dest, indexer, env ); -
src/ResolvExpr/ConversionCost.cc
r28e58fd r800d275 40 40 #define PRINT(x) 41 41 #endif 42 43 42 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 44 43 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) { … … 78 77 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 79 78 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 }); 81 82 } else { 82 83 ConversionCost converter( dest, indexer, env ); … … 90 91 } 91 92 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 ) { 93 94 PRINT( std::cerr << "convert to reference cost..." << std::endl; ) 94 95 if ( diff > 0 ) { 95 96 // 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 ); 97 98 cost.incReference(); 98 99 return cost; 99 100 } else if ( diff < -1 ) { 100 101 // 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 ); 102 103 cost.incReference(); 103 104 return cost; … … 110 111 return Cost::safe; 111 112 } 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 ); 113 114 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 114 115 if ( assignResult < 0 ) { … … 157 158 } 158 159 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 ) { 160 161 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 ); 162 163 } 163 164 -
src/ResolvExpr/ConversionCost.h
r28e58fd r800d275 16 16 #pragma once 17 17 18 #include <functional> // for function 19 18 20 #include "Cost.h" // for Cost 19 21 #include "SynTree/Visitor.h" // for Visitor … … 21 23 22 24 namespace SymTab { 23 class Indexer;25 class Indexer; 24 26 } // namespace SymTab 25 27 26 28 namespace ResolvExpr { 27 class TypeEnvironment;29 class TypeEnvironment; 28 30 29 31 class ConversionCost : public Visitor { … … 55 57 }; 56 58 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 ); 58 61 } // namespace ResolvExpr 59 62 -
src/ResolvExpr/Cost.h
r28e58fd r800d275 28 28 Cost & incSafe( int inc = 1 ); 29 29 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; } 30 35 31 36 Cost operator+( const Cost &other ) const;
Note:
See TracChangeset
for help on using the changeset viewer.