- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
r322b97e r5ccb10d 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 > … … 186 193 if ( alternatives.begin() == oldBegin ) { 187 194 std::ostringstream stream; 188 stream << "Can't choose between " << alternatives.size() << " alternatives for expression "; 195 AltList winners; 196 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) ); 197 stream << "Can't choose between " << winners.size() << " alternatives for expression "; 189 198 expr->print( stream ); 190 199 stream << "Alternatives are:"; 191 AltList winners;192 findMinCost( alternatives.begin(), alternatives.end(), back_inserter( winners ) );193 200 printAlts( winners, stream, 8 ); 194 201 throw SemanticError( stream.str() ); … … 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 } … … 228 241 void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 229 242 // by this point, member must be a name expr 230 NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member ); 243 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ); 244 if ( ! nameExpr ) return; 231 245 const std::string & name = nameExpr->get_name(); 232 246 std::list< Declaration* > members; … … 250 264 // during parsing and reusing that information here. 251 265 std::stringstream ss( constantExpr->get_constant()->get_value() ); 252 int val ;266 int val = 0; 253 267 std::string tmp; 254 268 if ( ss >> val && ! (ss >> tmp) ) { … … 277 291 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 278 292 279 Cost convCost ( 0, 0, 0 );293 Cost convCost = Cost::zero; 280 294 std::list< DeclarationWithType* >& formals = function->get_parameters(); 281 295 std::list< DeclarationWithType* >::iterator formal = formals.begin(); … … 290 304 actualType->print( std::cerr, 8 ); 291 305 ) 292 Cost actualCost ;306 Cost actualCost = Cost::zero; 293 307 if ( formal == formals.end() ) { 294 308 if ( function->get_isVarArgs() ) { 295 convCost += Cost( 1, 0, 0 ); 309 convCost.incUnsafe(); 310 // convert reference-typed expressions to value-typed expressions 311 referenceToRvalueConversion( *actualExpr ); 296 312 continue; 297 313 } else { … … 305 321 std::cerr << std::endl << " to "; 306 322 formalType->print( std::cerr, 8 ); 323 std::cerr << std::endl << "environment is: "; 324 alt.env.print( std::cerr, 8 ); 325 std::cerr << std::endl; 307 326 ) 308 327 Cost newCost = conversionCost( actualType, formalType, indexer, alt.env ); … … 316 335 convCost += newCost; 317 336 actualCost += newCost; 318 if ( actualCost != Cost ( 0, 0, 0 )) {337 if ( actualCost != Cost::zero ) { 319 338 Type *newType = formalType->clone(); 320 339 alt.env.apply( newType ); 321 340 *actualExpr = new CastExpr( *actualExpr, newType ); 322 341 } 323 convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0);342 convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) ); 324 343 ++formal; // can't be in for-loop update because of the continue 325 344 } … … 343 362 } 344 363 convCost += newCost; 345 convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0);364 convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) ); 346 365 } 347 366 … … 400 419 Expression * actual = actualIt->expr; 401 420 Type * actualType = actual->get_result(); 421 402 422 PRINT( 403 423 std::cerr << "formal type is "; … … 408 428 ) 409 429 if ( ! unify( formalType, actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 430 // std::cerr << "unify failed" << std::endl; 410 431 return false; 411 432 } … … 452 473 // match flattened actuals with formal parameters - actuals will be grouped to match 453 474 // with formals as appropriate 454 Cost cost ;475 Cost cost = Cost::zero; 455 476 std::list< Expression * > newExprs; 456 477 ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal ); … … 613 634 AssertionSet newNeed; 614 635 //AssertionParentSet needParents; 636 PRINT( 637 std::cerr << "env is: " << std::endl; 638 newAlt.env.print( std::cerr, 0 ); 639 std::cerr << std::endl; 640 ) 641 615 642 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out ); 616 643 // PRINT( … … 643 670 makeExprList( instantiatedActuals, appExpr->get_args() ); 644 671 PRINT( 672 std::cerr << "instantiate function success: " << appExpr << std::endl; 645 673 std::cerr << "need assertions:" << std::endl; 646 674 printAssertionSet( resultNeed, std::cerr, 8 ); … … 663 691 UntypedExpr *vexpr = untypedExpr->clone(); 664 692 vexpr->set_result( pt.clone() ); 665 alternatives.push_back( Alternative( vexpr, env, Cost ()) );693 alternatives.push_back( Alternative( vexpr, env, Cost::zero) ); 666 694 return; 667 695 } … … 681 709 AltList candidates; 682 710 SemanticError errors; 683 for ( AltList:: const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {711 for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) { 684 712 try { 685 713 PRINT( … … 688 716 ) 689 717 // check if the type is pointer to function 690 PointerType *pointer; 691 if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) { 718 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) { 692 719 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 720 referenceToRvalueConversion( func->expr ); 693 721 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 694 722 // XXX … … 696 724 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 697 725 } 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 726 } 727 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer) 728 referenceToRvalueConversion( func->expr ); 729 EqvClass eqvClass; 730 if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) { 731 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) { 732 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 733 makeFunctionAlternatives( *func, function, *actualAlt, std::back_inserter( candidates ) ); 734 } // for 706 735 } // if 707 736 } // if … … 722 751 } 723 752 724 for ( AltList:: const_iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) {753 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); funcOp != funcOpFinder.alternatives.end(); ++funcOp ) { 725 754 // check if the type is pointer to function 726 PointerType *pointer; 727 if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) { 755 if ( PointerType *pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result()->stripReferences() ) ) { 728 756 if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) { 757 referenceToRvalueConversion( funcOp->expr ); 729 758 for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) { 730 759 AltList currentAlt; … … 753 782 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 754 783 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 755 std::cerr << "Case +++++++++++++ "<< std::endl;784 std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl; 756 785 std::cerr << "formals are:" << std::endl; 757 786 printAll( function->get_parameters(), std::cerr, 8 ); … … 796 825 bool isLvalue( Expression *expr ) { 797 826 // xxx - recurse into tuples? 798 return expr->has_result() && expr->get_result()->get_lvalue();827 return expr->has_result() && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) ); 799 828 } 800 829 … … 810 839 811 840 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). 817 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 841 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) { 842 // Argument expression is a tuple and the target type is not void and not a reference type. 843 // Cast each member of the tuple to its corresponding target type, producing the tuple of those 844 // cast expressions. If there are more components of the tuple than components in the target type, 845 // then excess components do not come out in the result expression (but UniqueExprs ensure that 846 // side effects will still be done). 847 if ( Tuples::maybeImpureIgnoreUnique( argExpr ) ) { 818 848 // expressions which may contain side effects require a single unique instance of the expression. 819 849 argExpr = new UniqueExpr( argExpr ); … … 855 885 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 856 886 // to. 857 int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();887 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 858 888 if ( discardedValues < 0 ) continue; 859 889 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 860 890 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 861 891 // 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 );892 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 893 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 864 894 if ( thisCost != Cost::infinity ) { 865 895 // count one safe conversion for each value that is thrown away 866 thisCost += Cost( 0, 0,discardedValues );896 thisCost.incSafe( discardedValues ); 867 897 868 898 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); … … 895 925 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); 896 926 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() ); 927 // 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 928 std::unique_ptr<Expression> aggrExpr( agg->expr->clone() ); 929 Type * aggrType = aggrExpr->get_result(); 930 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 931 aggrType = aggrType->stripReferences(); 932 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) ); 933 } 934 // find member of the given type 935 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 936 addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 937 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 938 addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 939 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 940 addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() ); 903 941 } // if 904 942 } // for … … 915 953 for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) { 916 954 VariableExpr newExpr( *i, nameExpr->get_argName() ); 917 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );955 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 918 956 PRINT( 919 957 std::cerr << "decl is "; … … 941 979 void AlternativeFinder::visit( SizeofExpr *sizeofExpr ) { 942 980 if ( sizeofExpr->get_isType() ) { 943 Type * newType = sizeofExpr->get_type()->clone();944 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer )), env, Cost::zero ) );981 // xxx - resolveTypeof? 982 alternatives.push_back( Alternative( sizeofExpr->clone(), env, Cost::zero ) ); 945 983 } else { 946 984 // find all alternatives for the argument to sizeof … … 955 993 // return the lowest cost alternative for the argument 956 994 Alternative &choice = winners.front(); 995 referenceToRvalueConversion( choice.expr ); 957 996 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 958 997 } // if … … 961 1000 void AlternativeFinder::visit( AlignofExpr *alignofExpr ) { 962 1001 if ( alignofExpr->get_isType() ) { 963 Type * newType = alignofExpr->get_type()->clone();964 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer )), env, Cost::zero ) );1002 // xxx - resolveTypeof? 1003 alternatives.push_back( Alternative( alignofExpr->clone(), env, Cost::zero ) ); 965 1004 } else { 966 1005 // find all alternatives for the argument to sizeof … … 975 1014 // return the lowest cost alternative for the argument 976 1015 Alternative &choice = winners.front(); 1016 referenceToRvalueConversion( choice.expr ); 977 1017 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 978 1018 } // if … … 1059 1099 for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) { 1060 1100 VariableExpr newExpr( *i ); 1061 alternatives.push_back( Alternative( newExpr.clone(), env, Cost ()) );1101 alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) ); 1062 1102 renameTypes( alternatives.back().expr ); 1063 1103 } // for … … 1232 1272 if ( thisCost != Cost::infinity ) { 1233 1273 // count one safe conversion for each value that is thrown away 1234 thisCost += Cost( 0, 0,discardedValues );1274 thisCost.incSafe( discardedValues ); 1235 1275 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1236 1276 }
Note: See TracChangeset
for help on using the changeset viewer.