Changeset 4f748c5 for src/ResolvExpr
- Timestamp:
- Nov 2, 2017, 11:45:10 AM (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, with_gc
- Children:
- 6de43b6
- Parents:
- b1e68d03 (diff), fde89cf6 (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:
-
- 7 edited
-
AlternativeFinder.cc (modified) (9 diffs)
-
ConversionCost.cc (modified) (12 diffs)
-
PolyCost.cc (modified) (3 diffs)
-
PtrsAssignable.cc (modified) (6 diffs)
-
PtrsCastable.cc (modified) (4 diffs)
-
Resolver.cc (modified) (1 diff)
-
Unify.cc (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
rb1e68d03 r4f748c5 122 122 ) 123 123 mapPlace->second.isAmbiguous = true; 124 } else { 125 PRINT( 126 std::cerr << "cost " << candidate->cost << " loses to " << mapPlace->second.candidate->cost << std::endl; 127 ) 124 128 } 125 129 } else { … … 127 131 } 128 132 } 129 130 PRINT(131 std::cerr << "there are " << selected.size() << " alternatives before elimination" << std::endl;132 )133 133 134 134 // accept the alternatives that were unambiguous … … 181 181 } 182 182 if ( prune ) { 183 auto oldsize = alternatives.size(); 183 184 PRINT( 184 185 std::cerr << "alternatives before prune:" << std::endl; … … 198 199 } 199 200 alternatives.erase( oldBegin, alternatives.end() ); 201 PRINT( 202 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; 203 ) 200 204 PRINT( 201 205 std::cerr << "there are " << alternatives.size() << " alternatives after elimination" << std::endl; … … 319 323 Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) { 320 324 Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env ); 321 // if ( convCost != Cost::zero ) { 322 323 // xxx - temporary -- ignore poly cost, since this causes some polymorphic functions to be cast, which causes the specialize 324 // pass to try to specialize them, which currently does not work. Once that is fixed, remove the next 3 lines and uncomment the 325 // previous line. 325 326 // if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion. 327 // ignore poly cost for now, since this requires resolution of the cast to infer parameters and this 328 // does not currently work for the reason stated below. 326 329 Cost tmpCost = convCost; 327 330 tmpCost.incPoly( -tmpCost.get_polyCost() ); 328 331 if ( tmpCost != Cost::zero ) { 332 // if ( convCost != Cost::zero ) { 329 333 Type *newType = formalType->clone(); 330 334 env.apply( newType ); … … 632 636 std::cerr << std::endl; 633 637 ) 634 ApplicationExpr *appExpr = static_cast< ApplicationExpr* >( newerAlt.expr );635 638 // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter). 636 InferredParams * inferParameters = & appExpr->get_inferParams();639 InferredParams * inferParameters = &newerAlt.expr->get_inferParams(); 637 640 for ( UniqueId id : cur->second.idChain ) { 638 641 inferParameters = (*inferParameters)[ id ].inferParams.get(); … … 681 684 OpenVarSet openVars; 682 685 AssertionSet resultNeed, resultHave; 683 TypeEnvironment resultEnv ;686 TypeEnvironment resultEnv( func.env ); 684 687 makeUnifiableVars( funcType, openVars, resultNeed ); 685 688 resultEnv.add( funcType->get_forall() ); // add all type variables as open variables now so that those not used in the parameter list are still considered open … … 915 918 thisCost.incSafe( discardedValues ); 916 919 Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ); 917 // xxx - this doesn't work at the moment, since inferParameters requires an ApplicationExpr as the alternative. 918 // Once this works, it should be possible to infer parameters on a cast expression and specialize any function. 919 920 // inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 921 candidates.emplace_back( std::move( newAlt ) ); 920 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 922 921 } // if 923 922 } // for … … 1298 1297 // count one safe conversion for each value that is thrown away 1299 1298 thisCost.incSafe( discardedValues ); 1300 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1299 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1300 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1301 1301 } 1302 1302 } -
src/ResolvExpr/ConversionCost.cc
rb1e68d03 r4f748c5 28 28 29 29 namespace ResolvExpr { 30 const Cost Cost::zero = Cost( 0, 0, 0,0 );31 const Cost Cost::infinity = Cost( -1, -1, -1, -1 );32 const Cost Cost::unsafe = Cost( 1, 0, 0,0 );33 const Cost Cost::poly = Cost( 0, 1, 0,0 );34 const Cost Cost::safe = Cost( 0, 0, 1,0 );35 const Cost Cost::reference = Cost( 0, 0, 0,1 );30 const Cost Cost::zero = Cost( 0, 0, 0, 0 ); 31 const Cost Cost::infinity = Cost( -1, -1, -1, -1 ); 32 const Cost Cost::unsafe = Cost( 1, 0, 0, 0 ); 33 const Cost Cost::poly = Cost( 0, 1, 0, 0 ); 34 const Cost Cost::safe = Cost( 0, 0, 1, 0 ); 35 const Cost Cost::reference = Cost( 0, 0, 0, 1 ); 36 36 37 37 #if 0 … … 113 113 int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer ); 114 114 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 115 if ( assignResult <0 ) {115 if ( assignResult > 0 ) { 116 116 return Cost::safe; 117 } else if ( assignResult >0 ) {117 } else if ( assignResult < 0 ) { 118 118 return Cost::unsafe; 119 119 } // if … … 269 269 } 270 270 271 void ConversionCost::visit( PointerType *pointerType) {271 void ConversionCost::visit( PointerType * pointerType ) { 272 272 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 273 273 PRINT( std::cerr << pointerType << " ===> " << destAsPtr; ) … … 284 284 } 285 285 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 286 int assignResult = ptrsAssignable( pointerType-> get_base(), destAsPtr->get_base(), env );286 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env ); 287 287 PRINT( std::cerr << " :: " << assignResult << std::endl; ) 288 if ( assignResult <0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {288 if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) { 289 289 cost = Cost::safe; 290 } else if ( assignResult >0 ) {290 } else if ( assignResult < 0 ) { 291 291 cost = Cost::unsafe; 292 292 } // if 293 293 // assignResult == 0 means Cost::Infinity 294 294 } // if 295 } else if ( dynamic_cast< ZeroType * >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr) {295 } else if ( dynamic_cast< ZeroType * >( dest ) ) { 296 296 cost = Cost::unsafe; 297 297 } // if 298 298 } 299 299 300 void ConversionCost::visit( __attribute((unused)) ArrayType *arrayType) {}301 302 void ConversionCost::visit( ReferenceType *refType) {300 void ConversionCost::visit( ArrayType * ) {} 301 302 void ConversionCost::visit( ReferenceType * refType ) { 303 303 // Note: dest can never be a reference, since it would have been caught in an earlier check 304 304 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 317 317 } 318 318 319 void ConversionCost::visit( __attribute((unused)) FunctionType *functionType) {}320 321 void ConversionCost::visit( StructInstType *inst) {319 void ConversionCost::visit( FunctionType * ) {} 320 321 void ConversionCost::visit( StructInstType * inst ) { 322 322 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 323 323 if ( inst->name == destAsInst->name ) { … … 327 327 } 328 328 329 void ConversionCost::visit( UnionInstType *inst) {329 void ConversionCost::visit( UnionInstType * inst ) { 330 330 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 331 331 if ( inst->name == destAsInst->name ) { … … 335 335 } 336 336 337 void ConversionCost::visit( __attribute((unused)) EnumInstType *inst) {337 void ConversionCost::visit( EnumInstType * ) { 338 338 static Type::Qualifiers q; 339 339 static BasicType integer( q, BasicType::SignedInt ); … … 344 344 } 345 345 346 void ConversionCost::visit( __attribute((unused)) TraitInstType *inst) { 347 } 348 349 void ConversionCost::visit(TypeInstType *inst) { 346 void ConversionCost::visit( TraitInstType * ) {} 347 348 void ConversionCost::visit( TypeInstType *inst ) { 350 349 EqvClass eqvClass; 351 350 NamedTypeDecl *namedType; … … 366 365 } 367 366 368 void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {367 void ConversionCost::visit( TupleType * tupleType ) { 369 368 Cost c = Cost::zero; 370 if ( TupleType * destAsTuple = dynamic_cast< TupleType* >( dest ) ) {371 std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin();372 std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin();369 if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) { 370 std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin(); 371 std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin(); 373 372 while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) { 374 373 Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env ); … … 386 385 } 387 386 388 void ConversionCost::visit( __attribute((unused)) VarArgsType *varArgsType) {387 void ConversionCost::visit( VarArgsType * ) { 389 388 if ( dynamic_cast< VarArgsType* >( dest ) ) { 390 389 cost = Cost::zero; … … 392 391 } 393 392 394 void ConversionCost::visit( __attribute((unused)) ZeroType *zeroType) {395 if ( dynamic_cast< ZeroType * >( dest ) ) {393 void ConversionCost::visit( ZeroType * ) { 394 if ( dynamic_cast< ZeroType * >( dest ) ) { 396 395 cost = Cost::zero; 397 396 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { … … 409 408 } 410 409 411 void ConversionCost::visit( __attribute((unused)) OneType *oneType) {412 if ( dynamic_cast< OneType * >( dest ) ) {410 void ConversionCost::visit( OneType * ) { 411 if ( dynamic_cast< OneType * >( dest ) ) { 413 412 cost = Cost::zero; 414 413 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { -
src/ResolvExpr/PolyCost.cc
rb1e68d03 r4f748c5 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // PolyCost.cc -- 7 // PolyCost.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 31 31 }; 32 32 33 int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {33 int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) { 34 34 PolyCost coster( env, indexer ); 35 35 type->accept( coster ); … … 37 37 } 38 38 39 PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer &indexer ) : result( 0 ), env( env ), indexer( indexer ) {39 PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), env( env ), indexer( indexer ) { 40 40 } 41 41 42 void PolyCost::visit(TypeInstType * typeInst) {42 void PolyCost::visit(TypeInstType * typeInst) { 43 43 EqvClass eqvClass; 44 if ( env.lookup( typeInst-> get_name(), eqvClass ) ) {44 if ( env.lookup( typeInst->name, eqvClass ) ) { 45 45 if ( eqvClass.type ) { 46 if ( TypeInstType *otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) { 47 if ( indexer.lookupType( otherTypeInst->get_name() ) ) { 46 if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) { 47 if ( indexer.lookupType( otherTypeInst->name ) ) { 48 // bound to opaque type 48 49 result += 1; 49 50 } // if 50 51 } else { 52 // bound to concrete type 51 53 result += 1; 52 54 } // if -
src/ResolvExpr/PtrsAssignable.cc
rb1e68d03 r4f748c5 47 47 48 48 int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ) { 49 // std::cerr << "assignable: " << src << " | " << dest << std::endl; 49 50 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) { 50 51 EqvClass eqvClass; … … 54 55 } // if 55 56 if ( dynamic_cast< VoidType* >( dest ) ) { 56 return 1; 57 // void * = T * for any T is unsafe 58 // xxx - this should be safe, but that currently breaks the build 59 return -1; 57 60 } else { 58 61 PtrsAssignable ptrs( dest, env ); … … 65 68 66 69 void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType ) { 67 if ( dynamic_cast< FunctionType* >( dest ) ) {68 result = 0;69 } else {70 result = -1;70 if ( ! dynamic_cast< FunctionType* >( dest ) ) { 71 // T * = void * is safe for any T that is not a function type. 72 // xxx - this should be unsafe... 73 result = 1; 71 74 } // if 72 75 } … … 75 78 void PtrsAssignable::visit( __attribute__((unused)) PointerType *pointerType ) {} 76 79 void PtrsAssignable::visit( __attribute__((unused)) ArrayType *arrayType ) {} 77 void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) { 78 result = -1; 79 } 80 void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) {} 80 81 81 82 void PtrsAssignable::visit( __attribute__((unused)) StructInstType *inst ) {} … … 83 84 84 85 void PtrsAssignable::visit( EnumInstType * ) { 85 if ( dynamic_cast< EnumInstType* >( dest ) ) { 86 if ( dynamic_cast< BasicType* >( dest ) ) { 87 // int * = E *, etc. is safe. This isn't technically correct, as each 88 // enum has one basic type that it is compatible with, an that type can 89 // differ from enum to enum. Without replicating GCC's internal logic, 90 // there is no way to know which type this particular enum is compatible 91 // with, so punt on this for now. 86 92 result = 1; 87 } else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {88 result = bt->get_kind() == BasicType::SignedInt;89 93 } 90 94 } … … 94 98 EqvClass eqvClass; 95 99 if ( env.lookup( inst->get_name(), eqvClass ) && eqvClass.type ) { 100 // T * = S * for any S depends on the type bound to T 96 101 result = ptrsAssignable( eqvClass.type, dest, env ); 97 } else {98 result = 0;99 102 } // if 100 103 } -
src/ResolvExpr/PtrsCastable.cc
rb1e68d03 r4f748c5 50 50 }; 51 51 52 int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 53 if ( dynamic_cast< FunctionType* >( src ) ) { 54 return -1; 55 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) { 56 EqvClass eqvClass; 57 if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) { 58 if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) { 59 if ( tyDecl->get_kind() == TypeDecl::Ftype ) { 52 namespace { 53 int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 54 if ( dynamic_cast< FunctionType* >( src ) ) { 55 return -1; 56 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) { 57 EqvClass eqvClass; 58 if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) { 59 if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) { 60 if ( tyDecl->get_kind() == TypeDecl::Ftype ) { 61 return -1; 62 } // if 63 } //if 64 } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) { 65 if ( eqvClass.data.kind == TypeDecl::Ftype ) { 60 66 return -1; 61 67 } // if 62 } //if63 } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {64 if ( eqvClass.data.kind == TypeDecl::Ftype ) {65 return -1;66 68 } // if 67 } // if68 } //if69 return 1;70 }71 int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {72 return -1 * objectCast( src, env, indexer ); // reverse the sense of objectCast69 } //if 70 return 1; 71 } 72 int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 73 return -1 * objectCast( src, env, indexer ); // reverse the sense of objectCast 74 } 73 75 } 74 76 … … 93 95 } 94 96 95 void PtrsCastable::visit( __attribute__((unused)) VoidType *voidType) {97 void PtrsCastable::visit( VoidType * ) { 96 98 result = objectCast( dest, env, indexer ); 97 99 } 98 100 99 void PtrsCastable::visit( __attribute__((unused)) BasicType *basicType) {101 void PtrsCastable::visit( BasicType * ) { 100 102 result = objectCast( dest, env, indexer ); 101 103 } 102 104 103 void PtrsCastable::visit( __attribute__((unused)) PointerType *pointerType) {105 void PtrsCastable::visit( PointerType * ) { 104 106 result = objectCast( dest, env, indexer ); 105 107 } 106 108 107 void PtrsCastable::visit( __attribute__((unused)) ArrayType *arrayType) {109 void PtrsCastable::visit( ArrayType * ) { 108 110 result = objectCast( dest, env, indexer ); 109 111 } 110 112 111 void PtrsCastable::visit( __attribute__((unused)) FunctionType *functionType) {113 void PtrsCastable::visit( FunctionType * ) { 112 114 // result = -1; 113 115 result = functionCast( dest, env, indexer ); 114 116 } 115 117 116 void PtrsCastable::visit( __attribute__((unused)) StructInstType *inst) {118 void PtrsCastable::visit( StructInstType * ) { 117 119 result = objectCast( dest, env, indexer ); 118 120 } 119 121 120 void PtrsCastable::visit( __attribute__((unused)) UnionInstType *inst) {122 void PtrsCastable::visit( UnionInstType * ) { 121 123 result = objectCast( dest, env, indexer ); 122 124 } 123 125 124 void PtrsCastable::visit( __attribute__((unused)) EnumInstType *inst) {126 void PtrsCastable::visit( EnumInstType * ) { 125 127 if ( dynamic_cast< EnumInstType* >( dest ) ) { 126 128 result = 1; … … 136 138 } 137 139 138 void PtrsCastable::visit( __attribute__((unused)) TraitInstType *inst) {}140 void PtrsCastable::visit( TraitInstType * ) {} 139 141 140 142 void PtrsCastable::visit(TypeInstType *inst) { … … 143 145 } 144 146 145 void PtrsCastable::visit( __attribute__((unused)) TupleType *tupleType) {147 void PtrsCastable::visit( TupleType * ) { 146 148 result = objectCast( dest, env, indexer ); 147 149 } 148 150 149 void PtrsCastable::visit( __attribute__((unused)) VarArgsType *varArgsType) {151 void PtrsCastable::visit( VarArgsType * ) { 150 152 result = objectCast( dest, env, indexer ); 151 153 } 152 154 153 void PtrsCastable::visit( __attribute__((unused)) ZeroType *zeroType) {155 void PtrsCastable::visit( ZeroType * ) { 154 156 result = objectCast( dest, env, indexer ); 155 157 } 156 158 157 void PtrsCastable::visit( __attribute__((unused)) OneType *oneType) {159 void PtrsCastable::visit( OneType * ) { 158 160 result = objectCast( dest, env, indexer ); 159 161 } -
src/ResolvExpr/Resolver.cc
rb1e68d03 r4f748c5 593 593 initExpr->expr = nullptr; 594 594 std::swap( initExpr->env, newExpr->env ); 595 std::swap( initExpr->inferParams, newExpr->inferParams ) ; 595 596 delete initExpr; 596 597 -
src/ResolvExpr/Unify.cc
rb1e68d03 r4f748c5 138 138 bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) { 139 139 switch ( data.kind ) { 140 case TypeDecl::Any:141 140 case TypeDecl::Dtype: 142 141 // to bind to an object type variable, the type must not be a function type.
Note:
See TracChangeset
for help on using the changeset viewer.