- File:
-
- 1 edited
-
src/ResolvExpr/AlternativeFinder.cc (modified) (26 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
ra5f0529 rb1bead1 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 : Fri Mar 17 09:14:17 2017 13 // Update Count : 30 14 14 // 15 15 … … 67 67 68 68 Cost sumCost( const AltList &in ) { 69 Cost total ;69 Cost total = Cost::zero; 70 70 for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) { 71 71 total += i->cost; … … 144 144 expr->get_result()->accept( global_renamer ); 145 145 } 146 } 146 147 void referenceToRvalueConversion( Expression *& expr ) { 148 if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) { 149 // cast away reference from expr 150 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() ); 151 } 152 } 153 } // namespace 147 154 148 155 template< typename InputIterator, typename OutputIterator > … … 213 220 void AlternativeFinder::addAnonConversions( const Alternative & alt ) { 214 221 // adds anonymous member interpretations whenever an aggregate value type is seen. 215 Expression * expr = alt.expr->clone(); 216 std::unique_ptr< Expression > manager( expr ); // RAII for expr 217 alt.env.apply( expr->get_result() ); 218 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( expr->get_result() ) ) { 222 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 223 std::unique_ptr<Expression> aggrExpr( alt.expr->clone() ); 224 alt.env.apply( aggrExpr->get_result() ); 225 Type * aggrType = aggrExpr->get_result(); 226 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 227 aggrType = aggrType->stripReferences(); 228 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 229 } 230 231 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 219 232 NameExpr nameExpr( "" ); 220 addAggMembers( structInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );221 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( expr->get_result() ) ) {233 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 234 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 222 235 NameExpr nameExpr( "" ); 223 addAggMembers( unionInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );236 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr ); 224 237 } // if 225 238 } … … 277 290 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 278 291 279 Cost convCost ( 0, 0, 0 );292 Cost convCost = Cost::zero; 280 293 std::list< DeclarationWithType* >& formals = function->get_parameters(); 281 294 std::list< DeclarationWithType* >::iterator formal = formals.begin(); … … 290 303 actualType->print( std::cerr, 8 ); 291 304 ) 292 Cost actualCost ;305 Cost actualCost = Cost::zero; 293 306 if ( formal == formals.end() ) { 294 307 if ( function->get_isVarArgs() ) { 295 convCost += Cost( 1, 0, 0 ); 308 convCost.incUnsafe(); 309 // convert reference-typed expressions to value-typed expressions 310 referenceToRvalueConversion( *actualExpr ); 296 311 continue; 297 312 } else { … … 305 320 std::cerr << std::endl << " to "; 306 321 formalType->print( std::cerr, 8 ); 322 std::cerr << std::endl << "environment is: "; 323 alt.env.print( std::cerr, 8 ); 324 std::cerr << std::endl; 307 325 ) 308 326 Cost newCost = conversionCost( actualType, formalType, indexer, alt.env ); … … 316 334 convCost += newCost; 317 335 actualCost += newCost; 318 if ( actualCost != Cost ( 0, 0, 0 )) {336 if ( actualCost != Cost::zero ) { 319 337 Type *newType = formalType->clone(); 320 338 alt.env.apply( newType ); 321 339 *actualExpr = new CastExpr( *actualExpr, newType ); 322 340 } 323 convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0);341 convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) ); 324 342 ++formal; // can't be in for-loop update because of the continue 325 343 } … … 343 361 } 344 362 convCost += newCost; 345 convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0);363 convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) ); 346 364 } 347 365 … … 400 418 Expression * actual = actualIt->expr; 401 419 Type * actualType = actual->get_result(); 420 402 421 PRINT( 403 422 std::cerr << "formal type is "; … … 408 427 ) 409 428 if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 429 // std::cerr << "unify failed" << std::endl; 410 430 return false; 411 431 } … … 452 472 // match flattened actuals with formal parameters - actuals will be grouped to match 453 473 // with formals as appropriate 454 Cost cost ;474 Cost cost = Cost::zero; 455 475 std::list< Expression * > newExprs; 456 476 ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal ); … … 643 663 makeExprList( instantiatedActuals, appExpr->get_args() ); 644 664 PRINT( 665 std::cerr << "instantiate function success: " << appExpr << std::endl; 645 666 std::cerr << "need assertions:" << std::endl; 646 667 printAssertionSet( resultNeed, std::cerr, 8 ); … … 663 684 UntypedExpr *vexpr = untypedExpr->clone(); 664 685 vexpr->set_result( pt.clone() ); 665 alternatives.push_back( Alternative( vexpr, env, Cost ()) );686 alternatives.push_back( Alternative( vexpr, env, Cost::zero) ); 666 687 return; 667 688 } … … 681 702 AltList candidates; 682 703 SemanticError errors; 683 for ( AltList:: const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {704 for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) { 684 705 try { 685 706 PRINT( … … 688 709 ) 689 710 // check if the type is pointer to function 690 PointerType *pointer; 691 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) { 711 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) { 692 712 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 713 referenceToRvalueConversion( func->expr ); 693 714 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 694 715 // XXX … … 696 717 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 697 718 } 698 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( pointer->get_base() ) ) { 699 EqvClass eqvClass; 700 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 701 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 702 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 703 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 704 } // for 705 } // if 719 } 720 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 721 referenceToRvalueConversion( func->expr ); 722 EqvClass eqvClass; 723 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 724 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 725 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 726 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 727 } // for 706 728 } // if 707 729 } // if … … 722 744 } 723 745 724 for ( AltList:: const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {746 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 725 747 // check if the type is pointer to function 726 PointerType *pointer; 727 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) { 748 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) { 728 749 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 750 referenceToRvalueConversion( funcOp->expr ); 729 751 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 730 752 AltList currentAlt; … … 753 775 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 754 776 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 755 std::cerr << "Case +++++++++++++ "<< std::endl;777 std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl; 756 778 std::cerr << "formals are:" << std::endl; 757 779 printAll( function->get_parameters(), std::cerr, 8 ); … … 796 818 bool isLvalue( Expression *expr ) { 797 819 // xxx - recurse into tuples? 798 return expr->has_result() && expr->get_result()->get_lvalue();820 return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) ); 799 821 } 800 822 … … 810 832 811 833 Expression * restructureCast( Expression * argExpr, Type * toType ) { 812 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) { 813 // Argument expression is a tuple and the target type is not void. Cast each member of the tuple 814 // to its corresponding target type, producing the tuple of those cast expressions. If there are 815 // more components of the tuple than components in the target type, then excess components do not 816 // come out in the result expression (but UniqueExprs ensure that side effects will still be done). 834 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) { 835 // Argument expression is a tuple and the target type is not void and not a reference type. 836 // Cast each member of the tuple to its corresponding target type, producing the tuple of those 837 // cast expressions. If there are more components of the tuple than components in the target type, 838 // then excess components do not come out in the result expression (but UniqueExprs ensure that 839 // side effects will still be done). 817 840 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 818 841 // expressions which may contain side effects require a single unique instance of the expression. … … 855 878 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 856 879 // to. 857 int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();880 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 858 881 if ( discardedValues < 0 ) continue; 859 882 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 860 883 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 861 884 // unification run for side-effects 862 unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );863 Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );885 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 886 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 864 887 if ( thisCost != Cost::infinity ) { 865 888 // count one safe conversion for each value that is thrown away 866 thisCost += Cost( 0, 0,discardedValues );889 thisCost.incSafe( discardedValues ); 867 890 868 891 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); … … 878 901 } 879 902 880 void AlternativeFinder::visit( VirtualCastExpr * castExpr ) {881 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );882 AlternativeFinder finder( indexer, env );883 // don't prune here, since it's guaranteed all alternatives will have the same type884 // (giving the alternatives different types is half of the point of ConstructorExpr nodes)885 finder.findWithAdjustment( castExpr->get_arg(), false );886 for ( Alternative & alt : finder.alternatives ) {887 alternatives.push_back( Alternative(888 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),889 alt.env, alt.cost ) );890 }891 }892 893 903 void AlternativeFinder::visit( UntypedMemberExpr *memberExpr ) { 894 904 AlternativeFinder funcFinder( indexer, env ); 895 905 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); 896 906 for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) { 897 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) { 898 addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 899 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) { 900 addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 901 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( agg->expr->get_result() ) ) { 902 addTupleMembers( tupleType, agg->expr, agg->cost, agg->env, memberExpr->get_member() ); 907 // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value 908 std::unique_ptr<Expression> aggrExpr( agg->expr->clone() ); 909 Type * aggrType = aggrExpr->get_result(); 910 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 911 aggrType = aggrType->stripReferences(); 912 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 913 } 914 // find member of the given type 915 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 916 addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 917 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 918 addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 919 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 920 addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 903 921 } // if 904 922 } // for … … 915 933 for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) { 916 934 VariableExpr newExpr( *i, nameExpr->get_argName() ); 917 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );935 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 918 936 PRINT( 919 937 std::cerr << "decl is "; … … 1059 1077 for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) { 1060 1078 VariableExpr newExpr( *i ); 1061 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );1079 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 1062 1080 renameTypes( alternatives.back().expr ); 1063 1081 } // for … … 1232 1250 if ( thisCost != Cost::infinity ) { 1233 1251 // count one safe conversion for each value that is thrown away 1234 thisCost += Cost( 0, 0,discardedValues );1252 thisCost.incSafe( discardedValues ); 1235 1253 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1236 1254 }
Note:
See TracChangeset
for help on using the changeset viewer.