Changeset 9cdfb4d0 for src/ResolvExpr
- Timestamp:
- Jan 22, 2018, 3:09:01 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, with_gc
- Children:
- e23d20b
- Parents:
- 326cd2b (diff), 4bf3b2b (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:
-
- 11 edited
-
CastCost.cc (modified) (4 diffs)
-
CommonType.cc (modified) (6 diffs)
-
ConversionCost.cc (modified) (22 diffs)
-
ConversionCost.h (modified) (3 diffs)
-
CurrentObject.cc (modified) (4 diffs)
-
FindOpenVars.cc (modified) (3 diffs)
-
Occurs.cc (modified) (3 diffs)
-
PolyCost.cc (modified) (1 diff)
-
PtrsAssignable.cc (modified) (1 diff)
-
Resolver.cc (modified) (5 diffs)
-
Resolver.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CastCost.cc
r326cd2b r9cdfb4d0 31 31 32 32 namespace ResolvExpr { 33 classCastCost : public ConversionCost {33 struct CastCost : public ConversionCost { 34 34 public: 35 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );35 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ); 36 36 37 virtual void visit( BasicType *basicType ); 38 virtual void visit( PointerType *pointerType ); 37 using ConversionCost::previsit; 38 using ConversionCost::postvisit; 39 void postvisit( BasicType * basicType ); 40 void postvisit( PointerType * pointerType ); 39 41 }; 40 42 … … 52 54 // all typedefs should be gone by this point 53 55 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType ); 54 if ( type-> get_base()) {55 return castCost( src, type-> get_base(), indexer, env ) + Cost::safe;56 if ( type->base ) { 57 return castCost( src, type->base, indexer, env ) + Cost::safe; 56 58 } // if 57 59 } // if … … 74 76 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 75 77 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 76 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {78 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 77 79 return ptrsCastable( t1, t2, env, indexer ); 78 80 }); 79 81 } else { 80 CastCost converter( dest, indexer, env);82 PassVisitor<CastCost> converter( dest, indexer, env, castCost ); 81 83 src->accept( converter ); 82 if ( converter. get_cost() == Cost::infinity ) {84 if ( converter.pass.get_cost() == Cost::infinity ) { 83 85 return Cost::infinity; 84 86 } else { 85 87 // xxx - why are we adding cost 0 here? 86 return converter. get_cost() + Cost::zero;88 return converter.pass.get_cost() + Cost::zero; 87 89 } // if 88 90 } // if 89 91 } 90 92 91 CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )92 : ConversionCost( dest, indexer, env ) {93 CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 94 : ConversionCost( dest, indexer, env, costFunc ) { 93 95 } 94 96 95 void CastCost:: visit( BasicType *basicType ) {97 void CastCost::postvisit( BasicType *basicType ) { 96 98 PointerType *destAsPointer = dynamic_cast< PointerType* >( dest ); 97 99 if ( destAsPointer && basicType->isInteger() ) { … … 103 105 } 104 106 105 void CastCost:: visit( PointerType *pointerType ) {107 void CastCost::postvisit( PointerType *pointerType ) { 106 108 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 107 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType-> get_base(), destAsPtr->get_base(), indexer, env ) ) {109 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 108 110 cost = Cost::safe; 109 111 } else { 110 112 TypeEnvironment newEnv( env ); 111 newEnv.add( pointerType-> get_forall());112 newEnv.add( pointerType-> get_base()->get_forall());113 int castResult = ptrsCastable( pointerType-> get_base(), destAsPtr->get_base(), newEnv, indexer );113 newEnv.add( pointerType->forall ); 114 newEnv.add( pointerType->base->forall ); 115 int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer ); 114 116 if ( castResult > 0 ) { 115 117 cost = Cost::safe; -
src/ResolvExpr/CommonType.cc
r326cd2b r9cdfb4d0 91 91 // special case where one type has a reference depth of 1 larger than the other 92 92 if ( diff > 0 || diff < 0 ) { 93 // std::cerr << "reference depth diff: " << diff << std::endl; 93 94 Type * result = nullptr; 94 if ( ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 ) ) { 95 ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 ); 96 ReferenceType * ref2 = dynamic_cast< ReferenceType * >( type2 ); 97 if ( diff > 0 ) { 98 // deeper on the left 99 assert( ref1 ); 100 result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars ); 101 } else { 102 // deeper on the right 103 assert( ref2 ); 104 result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars ); 105 } 106 if ( result && ref1 ) { 95 107 // formal is reference, so result should be reference 96 result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars ); 97 if ( result ) result = new ReferenceType( ref1->get_qualifiers(), result ); 98 } else { 99 // formal is value, so result should be value 100 ReferenceType * ref2 = strict_dynamic_cast< ReferenceType * > ( type2 ); 101 result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars ); 108 // std::cerr << "formal is reference; result should be reference" << std::endl; 109 result = new ReferenceType( ref1->get_qualifiers(), result ); 102 110 } 103 111 // std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl; … … 180 188 } 181 189 182 void CommonType::visit( __attribute((unused)) VoidType *voidType) {}190 void CommonType::visit( VoidType * ) {} 183 191 184 192 void CommonType::visit( BasicType *basicType ) { … … 246 254 } 247 255 248 void CommonType::visit( __attribute((unused)) ArrayType *arrayType) {}256 void CommonType::visit( ArrayType * ) {} 249 257 250 258 void CommonType::visit( ReferenceType *refType ) { … … 283 291 } 284 292 285 void CommonType::visit( __attribute((unused)) FunctionType *functionType) {}286 void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType) {}287 void CommonType::visit( __attribute((unused)) UnionInstType *aggregateUseType) {}293 void CommonType::visit( FunctionType * ) {} 294 void CommonType::visit( StructInstType * ) {} 295 void CommonType::visit( UnionInstType * ) {} 288 296 289 297 void CommonType::visit( EnumInstType *enumInstType ) { … … 296 304 } 297 305 298 void CommonType::visit( __attribute((unused)) TraitInstType *aggregateUseType) {306 void CommonType::visit( TraitInstType * ) { 299 307 } 300 308 … … 321 329 } 322 330 323 void CommonType::visit( __attribute((unused)) TupleType *tupleType) {}324 void CommonType::visit( __attribute((unused)) VarArgsType *varArgsType) {}331 void CommonType::visit( TupleType * ) {} 332 void CommonType::visit( VarArgsType * ) {} 325 333 326 334 void CommonType::visit( ZeroType *zeroType ) { -
src/ResolvExpr/ConversionCost.cc
r326cd2b r9cdfb4d0 44 44 EqvClass eqvClass; 45 45 NamedTypeDecl *namedType; 46 PRINT( std::cerr << "type inst " << destAsTypeInst-> get_name(); )47 if ( env.lookup( destAsTypeInst-> get_name(), eqvClass ) ) {46 PRINT( std::cerr << "type inst " << destAsTypeInst->name; ) 47 if ( env.lookup( destAsTypeInst->name, eqvClass ) ) { 48 48 if ( eqvClass.type ) { 49 49 return conversionCost( src, eqvClass.type, indexer, env ); … … 51 51 return Cost::infinity; 52 52 } 53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst-> get_name()) ) ) {53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->name ) ) ) { 54 54 PRINT( std::cerr << " found" << std::endl; ) 55 55 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 56 56 // all typedefs should be gone by this point 57 57 assert( type ); 58 if ( type-> get_base()) {59 return conversionCost( src, type-> get_base(), indexer, env ) + Cost::safe;58 if ( type->base ) { 59 return conversionCost( src, type->base, indexer, env ) + Cost::safe; 60 60 } // if 61 61 } // if … … 77 77 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 78 78 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){ 80 80 return ptrsAssignable( t1, t2, env ); 81 81 }); 82 82 } else { 83 ConversionCost converter( dest, indexer, env);83 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 84 84 src->accept( converter ); 85 if ( converter. get_cost() == Cost::infinity ) {85 if ( converter.pass.get_cost() == Cost::infinity ) { 86 86 return Cost::infinity; 87 87 } else { 88 return converter. get_cost() + Cost::zero;88 return converter.pass.get_cost() + Cost::zero; 89 89 } // if 90 90 } // if … … 92 92 93 93 Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) { 94 PRINT( std::cerr << "convert to reference cost... diff " << diff << std::endl; )94 PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; ) 95 95 if ( diff > 0 ) { 96 96 // TODO: document this 97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )-> get_base(), dest, diff-1, indexer, env, func );97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func ); 98 98 cost.incReference(); 99 99 return cost; 100 100 } else if ( diff < -1 ) { 101 101 // TODO: document this 102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )-> get_base(), diff+1, indexer, env, func );102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func ); 103 103 cost.incReference(); 104 104 return cost; … … 108 108 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 109 109 PRINT( std::cerr << "converting between references" << std::endl; ) 110 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) { 111 return Cost::safe; 110 Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers(); 111 Type::Qualifiers tq2 = destAsRef->base->get_qualifiers(); 112 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) { 113 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 114 if ( tq1 == tq2 ) { 115 // types are the same 116 return Cost::zero; 117 } else { 118 // types are the same, except otherPointer has more qualifiers 119 return Cost::safe; 120 } 112 121 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 113 int assignResult = func( srcAsRef-> get_base(), destAsRef->get_base(), env, indexer);122 int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env ); 114 123 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 115 124 if ( assignResult > 0 ) { … … 121 130 } else { 122 131 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 123 ConversionCost converter( dest, indexer, env);132 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 124 133 src->accept( converter ); 125 return converter. get_cost();134 return converter.pass.get_cost(); 126 135 } // if 127 136 } else { … … 129 138 assert( diff == -1 && destAsRef ); 130 139 PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; ) 131 if ( typesCompatibleIgnoreQualifiers( src, destAsRef-> get_base(), indexer, env ) ) {140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) { 132 141 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 133 142 if ( src->get_lvalue() ) { … … 137 146 ) 138 147 // lvalue-to-reference conversion: cv lvalue T => cv T & 139 if ( src->get_qualifiers() == destAsRef-> get_base()->get_qualifiers() ) {148 if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) { 140 149 return Cost::reference; // cost needs to be non-zero to add cast 141 } if ( src->get_qualifiers() < destAsRef-> get_base()->get_qualifiers() ) {150 } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) { 142 151 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 143 152 } else { 144 153 return Cost::unsafe; 145 154 } // if 146 } else if ( destAsRef-> get_base()->get_const() ) {155 } else if ( destAsRef->base->get_const() ) { 147 156 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 148 157 // rvalue-to-const-reference conversion: T => const T & … … 164 173 } 165 174 166 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )167 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {175 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 176 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) { 168 177 } 169 178 … … 248 257 }; 249 258 250 void ConversionCost:: visit( __attribute((unused)) VoidType *voidType) {259 void ConversionCost::postvisit( VoidType * ) { 251 260 cost = Cost::infinity; 252 261 } 253 262 254 void ConversionCost:: visit(BasicType *basicType) {263 void ConversionCost::postvisit(BasicType *basicType) { 255 264 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { 256 265 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; … … 269 278 } 270 279 271 void ConversionCost:: visit( PointerType * pointerType ) {280 void ConversionCost::postvisit( PointerType * pointerType ) { 272 281 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 273 PRINT( std::cerr << pointerType << " ===> " << destAsPtr; ) 274 Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers(); 275 Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers(); 276 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { 282 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; ) 283 Type::Qualifiers tq1 = pointerType->base->get_qualifiers(); 284 Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers(); 285 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 286 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 277 287 if ( tq1 == tq2 ) { 278 288 // types are the same … … 280 290 } else { 281 291 // types are the same, except otherPointer has more qualifiers 282 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )283 292 cost = Cost::safe; 284 293 } 285 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?294 } else { 286 295 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env ); 287 296 PRINT( std::cerr << " :: " << assignResult << std::endl; ) 288 if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) { 289 cost = Cost::safe; 297 if ( assignResult > 0 && tq1 <= tq2 ) { 298 // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct? 299 if ( tq1 == tq2 ) { 300 cost = Cost::safe; 301 } else if ( tq1 < tq2 ) { 302 cost = Cost::safe+Cost::safe; 303 } 290 304 } else if ( assignResult < 0 ) { 291 305 cost = Cost::unsafe; … … 298 312 } 299 313 300 void ConversionCost:: visit( ArrayType * ) {}301 302 void ConversionCost:: visit( ReferenceType * refType ) {314 void ConversionCost::postvisit( ArrayType * ) {} 315 316 void ConversionCost::postvisit( ReferenceType * refType ) { 303 317 // Note: dest can never be a reference, since it would have been caught in an earlier check 304 318 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 306 320 // recursively compute conversion cost from T1 to T2. 307 321 // cv can be safely dropped because of 'implicit dereference' behavior. 308 refType->base->accept( *this);322 cost = costFunc( refType->base, dest, indexer, env ); 309 323 if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) { 310 324 cost.incReference(); // prefer exact qualifiers … … 317 331 } 318 332 319 void ConversionCost:: visit( FunctionType * ) {}320 321 void ConversionCost:: visit( StructInstType * inst ) {333 void ConversionCost::postvisit( FunctionType * ) {} 334 335 void ConversionCost::postvisit( StructInstType * inst ) { 322 336 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 323 337 if ( inst->name == destAsInst->name ) { … … 327 341 } 328 342 329 void ConversionCost:: visit( UnionInstType * inst ) {343 void ConversionCost::postvisit( UnionInstType * inst ) { 330 344 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 331 345 if ( inst->name == destAsInst->name ) { … … 335 349 } 336 350 337 void ConversionCost:: visit( EnumInstType * ) {351 void ConversionCost::postvisit( EnumInstType * ) { 338 352 static Type::Qualifiers q; 339 353 static BasicType integer( q, BasicType::SignedInt ); 340 integer.accept( *this); // safe if dest >= int354 cost = costFunc( &integer, dest, indexer, env ); // safe if dest >= int 341 355 if ( cost < Cost::unsafe ) { 342 356 cost.incSafe(); … … 344 358 } 345 359 346 void ConversionCost:: visit( TraitInstType * ) {}347 348 void ConversionCost:: visit( TypeInstType *inst ) {360 void ConversionCost::postvisit( TraitInstType * ) {} 361 362 void ConversionCost::postvisit( TypeInstType *inst ) { 349 363 EqvClass eqvClass; 350 364 NamedTypeDecl *namedType; 351 if ( env.lookup( inst-> get_name(), eqvClass ) ) {352 cost = co nversionCost( eqvClass.type, dest, indexer, env );365 if ( env.lookup( inst->name, eqvClass ) ) { 366 cost = costFunc( eqvClass.type, dest, indexer, env ); 353 367 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) { 354 if ( inst-> get_name() == destAsInst->get_name()) {368 if ( inst->name == destAsInst->name ) { 355 369 cost = Cost::zero; 356 370 } 357 } else if ( ( namedType = indexer.lookupType( inst-> get_name()) ) ) {371 } else if ( ( namedType = indexer.lookupType( inst->name ) ) ) { 358 372 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 359 373 // all typedefs should be gone by this point 360 374 assert( type ); 361 if ( type-> get_base()) {362 cost = co nversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;363 } // if 364 } // if 365 } 366 367 void ConversionCost:: visit( TupleType * tupleType ) {375 if ( type->base ) { 376 cost = costFunc( type->base, dest, indexer, env ) + Cost::safe; 377 } // if 378 } // if 379 } 380 381 void ConversionCost::postvisit( TupleType * tupleType ) { 368 382 Cost c = Cost::zero; 369 383 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();372 while ( srcIt != tupleType-> get_types().end() && destIt != destAsTuple->get_types().end() ) {373 Cost newCost = co nversionCost( *srcIt++, *destIt++, indexer, env );384 std::list< Type * >::const_iterator srcIt = tupleType->types.begin(); 385 std::list< Type * >::const_iterator destIt = destAsTuple->types.begin(); 386 while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) { 387 Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env ); 374 388 if ( newCost == Cost::infinity ) { 375 389 return; … … 377 391 c += newCost; 378 392 } // while 379 if ( destIt != destAsTuple-> get_types().end() ) {393 if ( destIt != destAsTuple->types.end() ) { 380 394 cost = Cost::infinity; 381 395 } else { … … 385 399 } 386 400 387 void ConversionCost:: visit( VarArgsType * ) {401 void ConversionCost::postvisit( VarArgsType * ) { 388 402 if ( dynamic_cast< VarArgsType* >( dest ) ) { 389 403 cost = Cost::zero; … … 391 405 } 392 406 393 void ConversionCost:: visit( ZeroType * ) {407 void ConversionCost::postvisit( ZeroType * ) { 394 408 if ( dynamic_cast< ZeroType * >( dest ) ) { 395 409 cost = Cost::zero; … … 408 422 } 409 423 410 void ConversionCost:: visit( OneType * ) {424 void ConversionCost::postvisit( OneType * ) { 411 425 if ( dynamic_cast< OneType * >( dest ) ) { 412 426 cost = Cost::zero; -
src/ResolvExpr/ConversionCost.h
r326cd2b r9cdfb4d0 19 19 20 20 #include "Cost.h" // for Cost 21 22 #include "Common/PassVisitor.h" 21 23 #include "SynTree/Visitor.h" // for Visitor 22 24 #include "SynTree/SynTree.h" // for Visitor Nodes … … 29 31 class TypeEnvironment; 30 32 31 class ConversionCost : public Visitor { 33 typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction; 34 struct ConversionCost : public WithShortCircuiting { 32 35 public: 33 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );36 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction ); 34 37 35 38 Cost get_cost() const { return cost; } 36 39 37 virtual void visit(VoidType *voidType); 38 virtual void visit(BasicType *basicType); 39 virtual void visit(PointerType *pointerType); 40 virtual void visit(ArrayType *arrayType); 41 virtual void visit(ReferenceType *refType); 42 virtual void visit(FunctionType *functionType); 43 virtual void visit(StructInstType *aggregateUseType); 44 virtual void visit(UnionInstType *aggregateUseType); 45 virtual void visit(EnumInstType *aggregateUseType); 46 virtual void visit(TraitInstType *aggregateUseType); 47 virtual void visit(TypeInstType *aggregateUseType); 48 virtual void visit(TupleType *tupleType); 49 virtual void visit(VarArgsType *varArgsType); 50 virtual void visit(ZeroType *zeroType); 51 virtual void visit(OneType *oneType); 40 void previsit( BaseSyntaxNode * ) { visit_children = false; } 41 42 void postvisit( VoidType * voidType ); 43 void postvisit( BasicType * basicType ); 44 void postvisit( PointerType * pointerType ); 45 void postvisit( ArrayType * arrayType ); 46 void postvisit( ReferenceType * refType ); 47 void postvisit( FunctionType * functionType ); 48 void postvisit( StructInstType * aggregateUseType ); 49 void postvisit( UnionInstType * aggregateUseType ); 50 void postvisit( EnumInstType * aggregateUseType ); 51 void postvisit( TraitInstType * aggregateUseType ); 52 void postvisit( TypeInstType * aggregateUseType ); 53 void postvisit( TupleType * tupleType ); 54 void postvisit( VarArgsType * varArgsType ); 55 void postvisit( ZeroType * zeroType ); 56 void postvisit( OneType * oneType ); 52 57 protected: 53 58 Type *dest; … … 55 60 Cost cost; 56 61 const TypeEnvironment &env; 62 CostFunction costFunc; 57 63 }; 58 64 59 typedef std::function<int(Type *, Type *, const TypeEnvironment &, const SymTab::Indexer&)> PtrsFunction;65 typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction; 60 66 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ); 61 67 } // namespace ResolvExpr -
src/ResolvExpr/CurrentObject.cc
r326cd2b r9cdfb4d0 38 38 39 39 namespace ResolvExpr { 40 long long int getConstValue( ConstantExpr * constExpr ) {41 if ( BasicType * basicType = dynamic_cast< BasicType * >( constExpr->get_result() ) ) {42 if ( basicType->isInteger() ) {43 return constExpr->get_constant()->get_ival();44 } else {45 assertf( false, "Non-integer constant expression in getConstValue %s", toString( constExpr ).c_str() ); // xxx - might be semantic error46 }47 } else if ( dynamic_cast< OneType * >( constExpr->get_result() ) ) {48 return 1;49 } else if ( dynamic_cast< ZeroType * >( constExpr->get_result() ) ) {50 return 0;51 } else {52 assertf( false, "unhandled type on getConstValue %s", toString( constExpr->get_result() ).c_str() ); // xxx - might be semantic error53 }54 }55 56 40 template< typename AggrInst > 57 41 TypeSubstitution makeGenericSubstitution( AggrInst * inst ) { … … 141 125 base = at->get_base(); 142 126 memberIter = createMemberIterator( base ); 127 if ( at->isVarLen ) throw SemanticError( "VLA initialization does not support @=", at ); 143 128 setSize( at->get_dimension() ); 144 129 } … … 151 136 void setSize( Expression * expr ) { 152 137 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 153 size = getConstValue( constExpr ); 154 PRINT( std::cerr << "array type with size: " << size << std::endl; ) 138 try { 139 size = constExpr->intValue(); 140 PRINT( std::cerr << "array type with size: " << size << std::endl; ) 141 } catch ( SemanticError & ) { 142 throw SemanticError( "Constant expression of non-integral type in array dimension: ", expr ); 143 } 155 144 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 156 145 setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast 146 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 147 if ( EnumInstType * inst = dynamic_cast< EnumInstType * > ( varExpr->result ) ) { 148 long long int value; 149 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 150 size = value; 151 } 152 } 157 153 } else { 158 154 assertf( false, "unhandled expression in setSize: %s", toString( expr ).c_str() ); // xxx - if not a constant expression, it's not simple to determine how long the array actually is, which is necessary for initialization to be done correctly -- fix this … … 164 160 // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions 165 161 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 166 index = getConstValue( constExpr ); 162 try { 163 index = constExpr->intValue(); 164 } catch( SemanticError & ) { 165 throw SemanticError( "Constant expression of non-integral type in array designator: ", expr ); 166 } 167 167 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 168 168 setPosition( castExpr->get_arg() ); 169 169 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 170 assertf( dynamic_cast<EnumInstType *> ( varExpr->get_result() ), "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() ); 171 index = 0; // xxx - get actual value of enum constant 170 EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() ); 171 assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() ); 172 long long int value; 173 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 174 index = value; 175 } 172 176 } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) { 173 177 index = 0; // xxx - get actual sizeof/alignof value? -
src/ResolvExpr/FindOpenVars.cc
r326cd2b r9cdfb4d0 19 19 #include <map> // for map<>::mapped_type 20 20 21 #include "Common/PassVisitor.h" 21 22 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType (ptr ... 22 23 #include "SynTree/Type.h" // for Type, Type::ForallList, ArrayType 23 #include "SynTree/Visitor.h" // for Visitor24 24 25 25 namespace ResolvExpr { 26 class FindOpenVars : public Visitor { 27 public: 26 struct FindOpenVars : public WithGuards { 28 27 FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 29 28 30 private: 31 virtual void visit(PointerType *pointerType); 32 virtual void visit(ArrayType *arrayType); 33 virtual void visit(FunctionType *functionType); 34 virtual void visit(TupleType *tupleType); 29 void previsit( PointerType * pointerType ); 30 void previsit( ArrayType * arrayType ); 31 void previsit( FunctionType * functionType ); 32 void previsit( TupleType * tupleType ); 35 33 36 34 void common_action( Type *type ); … … 42 40 43 41 void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) { 44 FindOpenVarsfinder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );42 PassVisitor<FindOpenVars> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen ); 45 43 type->accept( finder ); 46 44 } … … 70 68 } // for 71 69 } // if 72 /// std::c out<< "type is ";73 /// type->print( std::c out);74 /// std::c out<< std::endl << "need is" << std::endl;75 /// printAssertionSet( needAssertions, std::c out);76 /// std::c out<< std::endl << "have is" << std::endl;77 /// printAssertionSet( haveAssertions, std::c out);70 /// std::cerr << "type is "; 71 /// type->print( std::cerr ); 72 /// std::cerr << std::endl << "need is" << std::endl; 73 /// printAssertionSet( needAssertions, std::cerr ); 74 /// std::cerr << std::endl << "have is" << std::endl; 75 /// printAssertionSet( haveAssertions, std::cerr ); 78 76 } 79 77 80 void FindOpenVars:: visit(PointerType *pointerType) {78 void FindOpenVars::previsit(PointerType *pointerType) { 81 79 common_action( pointerType ); 82 Visitor::visit( pointerType );83 80 } 84 81 85 void FindOpenVars:: visit(ArrayType *arrayType) {82 void FindOpenVars::previsit(ArrayType *arrayType) { 86 83 common_action( arrayType ); 87 Visitor::visit( arrayType );88 84 } 89 85 90 void FindOpenVars:: visit(FunctionType *functionType) {86 void FindOpenVars::previsit(FunctionType *functionType) { 91 87 common_action( functionType ); 92 88 nextIsOpen = ! nextIsOpen; 93 Visitor::visit( functionType ); 94 nextIsOpen = ! nextIsOpen; 89 GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } ); 95 90 } 96 91 97 void FindOpenVars:: visit(TupleType *tupleType) {92 void FindOpenVars::previsit(TupleType *tupleType) { 98 93 common_action( tupleType ); 99 Visitor::visit( tupleType );100 94 } 101 95 } // namespace ResolvExpr -
src/ResolvExpr/Occurs.cc
r326cd2b r9cdfb4d0 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Occurs.cc -- 7 // Occurs.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 17 17 #include <string> // for string 18 18 19 #include "Common/PassVisitor.h" 19 20 #include "SynTree/Type.h" // for TypeInstType, Type 20 #include "SynTree/Visitor.h" // for Visitor21 21 #include "TypeEnvironment.h" // for EqvClass, TypeEnvironment 22 22 23 23 namespace ResolvExpr { 24 class Occurs : public Visitor { 25 public: 24 struct Occurs : public WithVisitorRef<Occurs> { 26 25 Occurs( std::string varName, const TypeEnvironment &env ); 27 bool get_result() const { return result; } 28 virtual void visit( TypeInstType *typeInst ); 29 private: 26 void previsit( TypeInstType * typeInst ); 27 30 28 bool result; 31 29 std::set< std::string > eqvVars; 32 const TypeEnvironment & env;30 const TypeEnvironment &tenv; 33 31 }; 34 32 35 33 bool occurs( Type *type, std::string varName, const TypeEnvironment &env ) { 36 Occursoccur( varName, env );34 PassVisitor<Occurs> occur( varName, env ); 37 35 type->accept( occur ); 38 return occur. get_result();36 return occur.pass.result; 39 37 } 40 38 41 Occurs::Occurs( std::string varName, const TypeEnvironment & env ) : result( false ),env( env ) {39 Occurs::Occurs( std::string varName, const TypeEnvironment & env ) : result( false ), tenv( env ) { 42 40 EqvClass eqvClass; 43 if ( env.lookup( varName, eqvClass ) ) {41 if ( tenv.lookup( varName, eqvClass ) ) { 44 42 eqvVars = eqvClass.vars; 45 43 } else { … … 48 46 } 49 47 50 void Occurs:: visit( TypeInstType *typeInst ) {48 void Occurs::previsit( TypeInstType * typeInst ) { 51 49 EqvClass eqvClass; 52 /// std::c out<< "searching for vars: ";53 /// std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::c out, " " ) );54 /// std::c out<< std::endl;50 /// std::cerr << "searching for vars: "; 51 /// std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cerr, " " ) ); 52 /// std::cerr << std::endl; 55 53 if ( eqvVars.find( typeInst->get_name() ) != eqvVars.end() ) { 56 54 result = true; 57 } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {55 } else if ( tenv.lookup( typeInst->get_name(), eqvClass ) ) { 58 56 if ( eqvClass.type ) { 59 /// std::c out<< typeInst->get_name() << " is bound to";60 /// eqvClass.type->print( std::c out);61 /// std::c out<< std::endl;62 eqvClass.type->accept( * this);57 /// std::cerr << typeInst->get_name() << " is bound to"; 58 /// eqvClass.type->print( std::cerr ); 59 /// std::cerr << std::endl; 60 eqvClass.type->accept( *visitor ); 63 61 } // if 64 62 } // if -
src/ResolvExpr/PolyCost.cc
r326cd2b r9cdfb4d0 14 14 // 15 15 16 #include "Common/PassVisitor.h" 16 17 #include "SymTab/Indexer.h" // for Indexer 17 18 #include "SynTree/Type.h" // for TypeInstType, Type 18 #include "SynTree/Visitor.h" // for Visitor19 19 #include "TypeEnvironment.h" // for EqvClass, TypeEnvironment 20 20 21 21 namespace ResolvExpr { 22 class PolyCost : public Visitor { 23 public: 22 struct PolyCost { 24 23 PolyCost( const TypeEnvironment &env, const SymTab::Indexer &indexer ); 25 int get_result() const { return result; } 26 private: 27 virtual void visit(TypeInstType *aggregateUseType); 24 25 void previsit( TypeInstType * aggregateUseType ); 28 26 int result; 29 const TypeEnvironment & env;27 const TypeEnvironment &tenv; 30 28 const SymTab::Indexer &indexer; 31 29 }; 32 30 33 31 int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) { 34 P olyCostcoster( env, indexer );32 PassVisitor<PolyCost> coster( env, indexer ); 35 33 type->accept( coster ); 36 return coster. get_result();34 return coster.pass.result; 37 35 } 38 36 39 PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), env( env ), indexer( indexer ) {37 PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), tenv( env ), indexer( indexer ) { 40 38 } 41 39 42 void PolyCost:: visit(TypeInstType * typeInst) {40 void PolyCost::previsit(TypeInstType * typeInst) { 43 41 EqvClass eqvClass; 44 if ( env.lookup( typeInst->name, eqvClass ) ) {42 if ( tenv.lookup( typeInst->name, eqvClass ) ) { 45 43 if ( eqvClass.type ) { 46 44 if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) { -
src/ResolvExpr/PtrsAssignable.cc
r326cd2b r9cdfb4d0 67 67 PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {} 68 68 69 void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType) {69 void PtrsAssignable::visit( VoidType * ) { 70 70 // T * = void * is disallowed - this is a change from C, where any 71 71 // void * can be assigned or passed to a non-void pointer without a cast. -
src/ResolvExpr/Resolver.cc
r326cd2b r9cdfb4d0 155 155 } // if 156 156 #endif 157 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end .");157 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end: (%zd) %s", finder.get_alternatives().size(), toString( untyped ).c_str() ); 158 158 Alternative &choice = finder.get_alternatives().front(); 159 159 Expression *newExpr = choice.expr->clone(); … … 171 171 172 172 namespace { 173 /// resolve `untyped` to the expression whose type satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 174 template<typename Pred> 175 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, Pred pred) { 176 TypeEnvironment env; 177 AlternativeFinder finder( indexer, env ); 178 finder.findWithAdjustment( untyped ); 179 180 AltList candidates; 181 for ( Alternative & alt : finder.get_alternatives() ) { 182 if ( pred( alt.expr->result ) ) { 183 candidates.push_back( std::move( alt ) ); 184 } 185 } 186 187 // choose the lowest cost expression among the candidates 188 AltList winners; 189 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 190 if ( winners.size() == 0 ) { 191 throw SemanticError( "No reasonable alternatives for " + kindStr + " expression: ", untyped ); 192 } else if ( winners.size() != 1 ) { 193 std::ostringstream stream; 194 stream << "Cannot choose between " << winners.size() << " alternatives for " + kindStr + " expression\n"; 195 untyped->print( stream ); 196 stream << "Alternatives are:\n"; 197 printAlts( winners, stream, 1 ); 198 throw SemanticError( stream.str() ); 199 } 200 201 // there is one unambiguous interpretation - move the expression into the with statement 202 Alternative & alt = winners.front(); 203 finishExpr( alt.expr, alt.env, untyped->env ); 204 delete untyped; 205 untyped = alt.expr; 206 alt.expr = nullptr; 207 } 208 173 209 bool isIntegralType( Type *type ) { 174 210 if ( dynamic_cast< EnumInstType * >( type ) ) { … … 184 220 185 221 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 186 TypeEnvironment env; 187 AlternativeFinder finder( indexer, env ); 188 finder.find( untyped ); 189 #if 0 190 if ( finder.get_alternatives().size() != 1 ) { 191 std::cout << "untyped expr is "; 192 untyped->print( std::cout ); 193 std::cout << std::endl << "alternatives are:"; 194 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 195 i->print( std::cout ); 196 } // for 197 } // if 198 #endif 199 Expression *newExpr = 0; 200 const TypeEnvironment *newEnv = 0; 201 for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 202 if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) { 203 if ( newExpr ) { 204 throw SemanticError( "Too many interpretations for case control expression", untyped ); 205 } else { 206 newExpr = i->expr->clone(); 207 newEnv = &i->env; 208 } // if 209 } // if 210 } // for 211 if ( ! newExpr ) { 212 throw SemanticError( "No interpretations for case control expression", untyped ); 213 } // if 214 finishExpr( newExpr, *newEnv, untyped->env ); 215 delete untyped; 216 untyped = newExpr; 217 } 218 222 findKindExpression( untyped, indexer, "condition", isIntegralType ); 223 } 219 224 } 220 225 … … 311 316 312 317 void Resolver::previsit( IfStmt *ifStmt ) { 313 find SingleExpression( ifStmt->condition, indexer );318 findIntegralExpression( ifStmt->condition, indexer ); 314 319 } 315 320 316 321 void Resolver::previsit( WhileStmt *whileStmt ) { 317 find SingleExpression( whileStmt->condition, indexer );322 findIntegralExpression( whileStmt->condition, indexer ); 318 323 } 319 324 320 325 void Resolver::previsit( ForStmt *forStmt ) { 321 326 if ( forStmt->condition ) { 322 find SingleExpression( forStmt->condition, indexer );327 findIntegralExpression( forStmt->condition, indexer ); 323 328 } // if 324 329 … … 579 584 } 580 585 586 581 587 void Resolver::previsit( WithStmt * withStmt ) { 582 588 for ( Expression *& expr : withStmt->exprs ) { 583 TypeEnvironment env;584 AlternativeFinder finder( indexer, env );585 finder.findWithAdjustment( expr );586 587 589 // only struct- and union-typed expressions are viable candidates 588 AltList candidates; 589 for ( Alternative & alt : finder.get_alternatives() ) { 590 if ( isStructOrUnion( alt.expr->result ) ) { 591 candidates.push_back( std::move( alt ) ); 592 } 593 } 594 595 // choose the lowest cost expression among the candidates 596 AltList winners; 597 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 598 if ( winners.size() == 0 ) { 599 throw SemanticError( "No reasonable alternatives for with statement expression: ", expr ); 600 } else if ( winners.size() != 1 ) { 601 std::ostringstream stream; 602 stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n"; 603 expr->print( stream ); 604 stream << "Alternatives are:\n"; 605 printAlts( winners, stream, 1 ); 606 throw SemanticError( stream.str() ); 607 } 608 609 // there is one unambiguous interpretation - move the expression into the with statement 610 Alternative & alt = winners.front(); 611 finishExpr( alt.expr, alt.env, expr->env ); 612 delete expr; 613 expr = alt.expr; 614 alt.expr = nullptr; 590 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 615 591 616 592 // if with expression might be impure, create a temporary so that it is evaluated once -
src/ResolvExpr/Resolver.h
r326cd2b r9cdfb4d0 33 33 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ); 34 34 void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer ); 35 void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer &indexer ); 35 36 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ); 36 37 void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
Note:
See TracChangeset
for help on using the changeset viewer.