Changeset b6838214 for src/ResolvExpr
- Timestamp:
- Jan 23, 2018, 5:46:43 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:
- 258e6ad5
- Parents:
- b158d8f (diff), 15d248e (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:
-
- 1 deleted
- 17 edited
-
AlternativeFinder.cc (modified) (41 diffs)
-
AlternativeFinder.h (modified) (2 diffs)
-
CastCost.cc (modified) (4 diffs)
-
CommonType.cc (modified) (11 diffs)
-
ConversionCost.cc (modified) (22 diffs)
-
ConversionCost.h (modified) (3 diffs)
-
CurrentObject.cc (modified) (8 diffs)
-
FindOpenVars.cc (modified) (3 diffs)
-
Occurs.cc (modified) (3 diffs)
-
PolyCost.cc (modified) (1 diff)
-
PtrsAssignable.cc (modified) (6 diffs)
-
PtrsCastable.cc (modified) (7 diffs)
-
RenameVars.cc (modified) (2 diffs)
-
RenameVars.h (modified) (1 diff)
-
Resolver.cc (modified) (6 diffs)
-
Resolver.h (modified) (1 diff)
-
TypeMap.h (deleted)
-
Unify.cc (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AlternativeFinder.cc
rb158d8f rb6838214 60 60 61 61 namespace ResolvExpr { 62 struct AlternativeFinder::Finder : public WithShortCircuiting { 63 Finder( AlternativeFinder & altFinder ) : altFinder( altFinder ), indexer( altFinder.indexer ), alternatives( altFinder.alternatives ), env( altFinder.env ), targetType( altFinder.targetType ) {} 64 65 void previsit( BaseSyntaxNode * ) { visit_children = false; } 66 67 void postvisit( ApplicationExpr * applicationExpr ); 68 void postvisit( UntypedExpr * untypedExpr ); 69 void postvisit( AddressExpr * addressExpr ); 70 void postvisit( LabelAddressExpr * labelExpr ); 71 void postvisit( CastExpr * castExpr ); 72 void postvisit( VirtualCastExpr * castExpr ); 73 void postvisit( UntypedMemberExpr * memberExpr ); 74 void postvisit( MemberExpr * memberExpr ); 75 void postvisit( NameExpr * variableExpr ); 76 void postvisit( VariableExpr * variableExpr ); 77 void postvisit( ConstantExpr * constantExpr ); 78 void postvisit( SizeofExpr * sizeofExpr ); 79 void postvisit( AlignofExpr * alignofExpr ); 80 void postvisit( UntypedOffsetofExpr * offsetofExpr ); 81 void postvisit( OffsetofExpr * offsetofExpr ); 82 void postvisit( OffsetPackExpr * offsetPackExpr ); 83 void postvisit( AttrExpr * attrExpr ); 84 void postvisit( LogicalExpr * logicalExpr ); 85 void postvisit( ConditionalExpr * conditionalExpr ); 86 void postvisit( CommaExpr * commaExpr ); 87 void postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ); 88 void postvisit( ConstructorExpr * ctorExpr ); 89 void postvisit( RangeExpr * rangeExpr ); 90 void postvisit( UntypedTupleExpr * tupleExpr ); 91 void postvisit( TupleExpr * tupleExpr ); 92 void postvisit( TupleIndexExpr * tupleExpr ); 93 void postvisit( TupleAssignExpr * tupleExpr ); 94 void postvisit( UniqueExpr * unqExpr ); 95 void postvisit( StmtExpr * stmtExpr ); 96 void postvisit( UntypedInitExpr * initExpr ); 97 98 /// Adds alternatives for anonymous members 99 void addAnonConversions( const Alternative & alt ); 100 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 101 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 102 /// Adds alternatives for member expressions where the left side has tuple type 103 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 104 /// Adds alternatives for offsetof expressions, given the base type and name of the member 105 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 106 /// Takes a final result and checks if its assertions can be satisfied 107 template<typename OutputIterator> 108 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out ); 109 /// Finds matching alternatives for a function, given a set of arguments 110 template<typename OutputIterator> 111 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 112 /// Checks if assertion parameters match for a new alternative 113 template< typename OutputIterator > 114 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); 115 private: 116 AlternativeFinder & altFinder; 117 const SymTab::Indexer &indexer; 118 AltList & alternatives; 119 const TypeEnvironment &env; 120 Type *& targetType; 121 }; 122 62 123 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) { 63 124 CastExpr *castToVoid = new CastExpr( expr ); … … 152 213 153 214 void renameTypes( Expression *expr ) { 154 expr->get_result()->accept( global_renamer);215 renameTyVars( expr->result ); 155 216 } 156 217 } // namespace … … 185 246 186 247 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) { 187 expr->accept( *this ); 248 PassVisitor<Finder> finder( *this ); 249 expr->accept( finder ); 188 250 if ( failFast && alternatives.empty() ) { 189 251 PRINT( … … 244 306 } 245 307 246 void AlternativeFinder:: addAnonConversions( const Alternative & alt ) {308 void AlternativeFinder::Finder::addAnonConversions( const Alternative & alt ) { 247 309 // adds anonymous member interpretations whenever an aggregate value type is seen. 248 310 // 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 … … 265 327 266 328 template< typename StructOrUnionType > 267 void AlternativeFinder:: addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {329 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 268 330 // by this point, member must be a name expr 269 331 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ); … … 284 346 } 285 347 286 void AlternativeFinder:: addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {348 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 287 349 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 288 350 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning … … 308 370 } 309 371 310 void AlternativeFinder:: visit( ApplicationExpr *applicationExpr ) {372 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 311 373 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 312 374 } … … 485 547 Type *adjType = candidate->get_type()->clone(); 486 548 adjustExprType( adjType, newEnv, indexer ); 487 adjType->accept( global_renamer);549 renameTyVars( adjType ); 488 550 PRINT( 489 551 std::cerr << "unifying "; … … 541 603 542 604 template< typename OutputIterator > 543 void AlternativeFinder:: inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {605 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) { 544 606 // PRINT( 545 607 // std::cerr << "inferParameters: assertions needed are" << std::endl; … … 596 658 ArgPack() 597 659 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 598 599 660 tupleStart(0), nextExpl(0), explAlt(0) {} 600 661 … … 706 767 Type* argType; 707 768 708 if ( nTuples > 0 ) { 709 // first iteration, push empty tuple expression 769 if ( nTuples > 0 || ! results[i].expr ) { 770 // first iteration or no expression to clone, 771 // push empty tuple expression 710 772 newResult.parent = i; 711 773 std::list<Expression*> emptyList; … … 892 954 893 955 template<typename OutputIterator> 894 void AlternativeFinder:: validateFunctionAlternative( const Alternative &func, ArgPack& result,956 void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 895 957 const std::vector<ArgPack>& results, OutputIterator out ) { 896 958 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); … … 915 977 916 978 template<typename OutputIterator> 917 void AlternativeFinder:: makeFunctionAlternatives( const Alternative &func,979 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 918 980 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 919 981 OpenVarSet funcOpenVars; … … 1022 1084 } 1023 1085 1024 void AlternativeFinder:: visit( UntypedExpr *untypedExpr ) {1086 void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) { 1025 1087 AlternativeFinder funcFinder( indexer, env ); 1026 1088 funcFinder.findWithAdjustment( untypedExpr->get_function() ); … … 1029 1091 1030 1092 std::vector< AlternativeFinder > argAlternatives; 1031 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),1093 altFinder.findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 1032 1094 back_inserter( argAlternatives ) ); 1033 1095 1034 1096 // take care of possible tuple assignments 1035 1097 // if not tuple assignment, assignment is taken care of as a normal function call 1036 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );1098 Tuples::handleTupleAssignment( altFinder, untypedExpr, argAlternatives ); 1037 1099 1038 1100 // find function operators … … 1172 1234 // fix this issue in a more robust way. 1173 1235 targetType = nullptr; 1174 visit( untypedExpr );1236 postvisit( untypedExpr ); 1175 1237 } 1176 1238 } … … 1181 1243 } 1182 1244 1183 void AlternativeFinder:: visit( AddressExpr *addressExpr ) {1245 void AlternativeFinder::Finder::postvisit( AddressExpr *addressExpr ) { 1184 1246 AlternativeFinder finder( indexer, env ); 1185 1247 finder.find( addressExpr->get_arg() ); … … 1192 1254 } 1193 1255 1194 void AlternativeFinder:: visit( LabelAddressExpr * expr ) {1256 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1195 1257 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1196 1258 } … … 1223 1285 } 1224 1286 1225 void AlternativeFinder:: visit( CastExpr *castExpr ) {1287 void AlternativeFinder::Finder::postvisit( CastExpr *castExpr ) { 1226 1288 Type *& toType = castExpr->get_result(); 1227 1289 assert( toType ); … … 1278 1340 } 1279 1341 1280 void AlternativeFinder:: visit( VirtualCastExpr * castExpr ) {1342 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1281 1343 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." ); 1282 1344 AlternativeFinder finder( indexer, env ); … … 1290 1352 } 1291 1353 1292 void AlternativeFinder:: visit( UntypedMemberExpr *memberExpr ) {1354 void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) { 1293 1355 AlternativeFinder funcFinder( indexer, env ); 1294 1356 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); … … 1312 1374 } 1313 1375 1314 void AlternativeFinder:: visit( MemberExpr *memberExpr ) {1376 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1315 1377 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1316 1378 } 1317 1379 1318 void AlternativeFinder:: visit( NameExpr *nameExpr ) {1380 void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) { 1319 1381 std::list< SymTab::Indexer::IdData > declList; 1320 1382 indexer.lookupId( nameExpr->get_name(), declList ); … … 1337 1399 } 1338 1400 1339 void AlternativeFinder:: visit( VariableExpr *variableExpr ) {1401 void AlternativeFinder::Finder::postvisit( VariableExpr *variableExpr ) { 1340 1402 // not sufficient to clone here, because variable's type may have changed 1341 1403 // since the VariableExpr was originally created. … … 1343 1405 } 1344 1406 1345 void AlternativeFinder:: visit( ConstantExpr *constantExpr ) {1407 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1346 1408 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1347 1409 } 1348 1410 1349 void AlternativeFinder:: visit( SizeofExpr *sizeofExpr ) {1411 void AlternativeFinder::Finder::postvisit( SizeofExpr *sizeofExpr ) { 1350 1412 if ( sizeofExpr->get_isType() ) { 1351 1413 Type * newType = sizeofExpr->get_type()->clone(); … … 1368 1430 } 1369 1431 1370 void AlternativeFinder:: visit( AlignofExpr *alignofExpr ) {1432 void AlternativeFinder::Finder::postvisit( AlignofExpr *alignofExpr ) { 1371 1433 if ( alignofExpr->get_isType() ) { 1372 1434 Type * newType = alignofExpr->get_type()->clone(); … … 1390 1452 1391 1453 template< typename StructOrUnionType > 1392 void AlternativeFinder:: addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {1454 void AlternativeFinder::Finder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) { 1393 1455 std::list< Declaration* > members; 1394 1456 aggInst->lookup( name, members ); … … 1403 1465 } 1404 1466 1405 void AlternativeFinder:: visit( UntypedOffsetofExpr *offsetofExpr ) {1467 void AlternativeFinder::Finder::postvisit( UntypedOffsetofExpr *offsetofExpr ) { 1406 1468 AlternativeFinder funcFinder( indexer, env ); 1407 1469 // xxx - resolveTypeof? … … 1413 1475 } 1414 1476 1415 void AlternativeFinder:: visit( OffsetofExpr *offsetofExpr ) {1477 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1416 1478 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1417 1479 } 1418 1480 1419 void AlternativeFinder:: visit( OffsetPackExpr *offsetPackExpr ) {1481 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1420 1482 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1421 1483 } … … 1444 1506 } 1445 1507 1446 void AlternativeFinder:: visit( AttrExpr *attrExpr ) {1508 void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) { 1447 1509 // assume no 'pointer-to-attribute' 1448 1510 NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() ); … … 1458 1520 if ( function->get_parameters().size() == 1 ) { 1459 1521 if ( attrExpr->get_isType() ) { 1460 resolveAttr( data, function, attrExpr->get_type(), env, *this);1522 resolveAttr( data, function, attrExpr->get_type(), env, altFinder); 1461 1523 } else { 1462 1524 AlternativeFinder finder( indexer, env ); … … 1464 1526 for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) { 1465 1527 if ( choice->expr->get_result()->size() == 1 ) { 1466 resolveAttr(data, function, choice->expr->get_result(), choice->env, *this);1528 resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder ); 1467 1529 } // fi 1468 1530 } // for … … 1479 1541 } 1480 1542 1481 void AlternativeFinder:: visit( LogicalExpr *logicalExpr ) {1543 void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) { 1482 1544 AlternativeFinder firstFinder( indexer, env ); 1483 1545 firstFinder.findWithAdjustment( logicalExpr->get_arg1() ); … … 1492 1554 } 1493 1555 1494 void AlternativeFinder:: visit( ConditionalExpr *conditionalExpr ) {1556 void AlternativeFinder::Finder::postvisit( ConditionalExpr *conditionalExpr ) { 1495 1557 // find alternatives for condition 1496 1558 AlternativeFinder firstFinder( indexer, env ); … … 1524 1586 } 1525 1587 1526 void AlternativeFinder:: visit( CommaExpr *commaExpr ) {1588 void AlternativeFinder::Finder::postvisit( CommaExpr *commaExpr ) { 1527 1589 TypeEnvironment newEnv( env ); 1528 1590 Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv ); … … 1535 1597 } 1536 1598 1537 void AlternativeFinder:: visit( RangeExpr * rangeExpr ) {1599 void AlternativeFinder::Finder::postvisit( RangeExpr * rangeExpr ) { 1538 1600 // resolve low and high, accept alternatives whose low and high types unify 1539 1601 AlternativeFinder firstFinder( indexer, env ); … … 1557 1619 } 1558 1620 1559 void AlternativeFinder:: visit( UntypedTupleExpr *tupleExpr ) {1621 void AlternativeFinder::Finder::postvisit( UntypedTupleExpr *tupleExpr ) { 1560 1622 std::vector< AlternativeFinder > subExprAlternatives; 1561 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),1623 altFinder.findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1562 1624 back_inserter( subExprAlternatives ) ); 1563 1625 std::vector< AltList > possibilities; … … 1575 1637 } 1576 1638 1577 void AlternativeFinder:: visit( TupleExpr *tupleExpr ) {1639 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1578 1640 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1579 1641 } 1580 1642 1581 void AlternativeFinder:: visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {1643 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1582 1644 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1583 1645 } 1584 1646 1585 void AlternativeFinder:: visit( ConstructorExpr * ctorExpr ) {1647 void AlternativeFinder::Finder::postvisit( ConstructorExpr * ctorExpr ) { 1586 1648 AlternativeFinder finder( indexer, env ); 1587 1649 // don't prune here, since it's guaranteed all alternatives will have the same type … … 1593 1655 } 1594 1656 1595 void AlternativeFinder:: visit( TupleIndexExpr *tupleExpr ) {1657 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1596 1658 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1597 1659 } 1598 1660 1599 void AlternativeFinder:: visit( TupleAssignExpr *tupleAssignExpr ) {1661 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1600 1662 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1601 1663 } 1602 1664 1603 void AlternativeFinder:: visit( UniqueExpr *unqExpr ) {1665 void AlternativeFinder::Finder::postvisit( UniqueExpr *unqExpr ) { 1604 1666 AlternativeFinder finder( indexer, env ); 1605 1667 finder.findWithAdjustment( unqExpr->get_expr() ); … … 1611 1673 } 1612 1674 1613 void AlternativeFinder:: visit( StmtExpr *stmtExpr ) {1675 void AlternativeFinder::Finder::postvisit( StmtExpr *stmtExpr ) { 1614 1676 StmtExpr * newStmtExpr = stmtExpr->clone(); 1615 1677 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); … … 1618 1680 } 1619 1681 1620 void AlternativeFinder:: visit( UntypedInitExpr *initExpr ) {1682 void AlternativeFinder::Finder::postvisit( UntypedInitExpr *initExpr ) { 1621 1683 // handle each option like a cast 1622 1684 AltList candidates; 1623 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; ) 1685 PRINT( 1686 std::cerr << "untyped init expr: " << initExpr << std::endl; 1687 ) 1624 1688 // O(N^2) checks of d-types with e-types 1625 1689 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) { … … 1637 1701 AssertionSet needAssertions, haveAssertions; 1638 1702 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1639 PRINT( std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; ) 1703 PRINT( 1704 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1705 ) 1640 1706 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1641 1707 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results -
src/ResolvExpr/AlternativeFinder.h
rb158d8f rb6838214 38 38 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >; 39 39 40 class AlternativeFinder : public Visitor{40 class AlternativeFinder { 41 41 public: 42 42 AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env ); … … 94 94 void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out ); 95 95 private: 96 virtual void visit( ApplicationExpr *applicationExpr ); 97 virtual void visit( UntypedExpr *untypedExpr ); 98 virtual void visit( AddressExpr *addressExpr ); 99 virtual void visit( LabelAddressExpr *labelExpr ); 100 virtual void visit( CastExpr *castExpr ); 101 virtual void visit( VirtualCastExpr *castExpr ); 102 virtual void visit( UntypedMemberExpr *memberExpr ); 103 virtual void visit( MemberExpr *memberExpr ); 104 virtual void visit( NameExpr *variableExpr ); 105 virtual void visit( VariableExpr *variableExpr ); 106 virtual void visit( ConstantExpr *constantExpr ); 107 virtual void visit( SizeofExpr *sizeofExpr ); 108 virtual void visit( AlignofExpr *alignofExpr ); 109 virtual void visit( UntypedOffsetofExpr *offsetofExpr ); 110 virtual void visit( OffsetofExpr *offsetofExpr ); 111 virtual void visit( OffsetPackExpr *offsetPackExpr ); 112 virtual void visit( AttrExpr *attrExpr ); 113 virtual void visit( LogicalExpr *logicalExpr ); 114 virtual void visit( ConditionalExpr *conditionalExpr ); 115 virtual void visit( CommaExpr *commaExpr ); 116 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ); 117 virtual void visit( ConstructorExpr * ctorExpr ); 118 virtual void visit( RangeExpr * rangeExpr ); 119 virtual void visit( UntypedTupleExpr *tupleExpr ); 120 virtual void visit( TupleExpr *tupleExpr ); 121 virtual void visit( TupleIndexExpr *tupleExpr ); 122 virtual void visit( TupleAssignExpr *tupleExpr ); 123 virtual void visit( UniqueExpr *unqExpr ); 124 virtual void visit( StmtExpr *stmtExpr ); 125 virtual void visit( UntypedInitExpr *initExpr ); 126 127 /// Adds alternatives for anonymous members 128 void addAnonConversions( const Alternative & alt ); 129 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 130 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 131 /// Adds alternatives for member expressions where the left side has tuple type 132 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 133 /// Adds alternatives for offsetof expressions, given the base type and name of the member 134 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 135 /// Takes a final result and checks if its assertions can be satisfied 136 template<typename OutputIterator> 137 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out ); 138 /// Finds matching alternatives for a function, given a set of arguments 139 template<typename OutputIterator> 140 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 141 /// Checks if assertion parameters match for a new alternative 142 template< typename OutputIterator > 143 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); 144 96 struct Finder; 145 97 const SymTab::Indexer &indexer; 146 98 AltList alternatives; -
src/ResolvExpr/CastCost.cc
rb158d8f rb6838214 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
rb158d8f rb6838214 18 18 #include <utility> // for pair 19 19 20 #include "Common/PassVisitor.h" 20 21 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet 21 22 #include "SymTab/Indexer.h" // for Indexer … … 29 30 30 31 namespace ResolvExpr { 31 class CommonType : public Visitor { 32 public: 32 struct CommonType : public WithShortCircuiting { 33 33 CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 34 34 Type *get_result() const { return result; } 35 36 void previsit( BaseSyntaxNode * ) { visit_children = false; } 37 38 void postvisit( VoidType * voidType ); 39 void postvisit( BasicType * basicType ); 40 void postvisit( PointerType * pointerType ); 41 void postvisit( ArrayType * arrayType ); 42 void postvisit( ReferenceType * refType ); 43 void postvisit( FunctionType * functionType ); 44 void postvisit( StructInstType * aggregateUseType ); 45 void postvisit( UnionInstType * aggregateUseType ); 46 void postvisit( EnumInstType * aggregateUseType ); 47 void postvisit( TraitInstType * aggregateUseType ); 48 void postvisit( TypeInstType * aggregateUseType ); 49 void postvisit( TupleType * tupleType ); 50 void postvisit( VarArgsType * varArgsType ); 51 void postvisit( ZeroType * zeroType ); 52 void postvisit( OneType * oneType ); 53 35 54 private: 36 virtual void visit( VoidType *voidType );37 virtual void visit( BasicType *basicType );38 virtual void visit( PointerType *pointerType );39 virtual void visit( ArrayType *arrayType );40 virtual void visit( ReferenceType *refType );41 virtual void visit( FunctionType *functionType );42 virtual void visit( StructInstType *aggregateUseType );43 virtual void visit( UnionInstType *aggregateUseType );44 virtual void visit( EnumInstType *aggregateUseType );45 virtual void visit( TraitInstType *aggregateUseType );46 virtual void visit( TypeInstType *aggregateUseType );47 virtual void visit( TupleType *tupleType );48 virtual void visit( VarArgsType *varArgsType );49 virtual void visit( ZeroType *zeroType );50 virtual void visit( OneType *oneType );51 52 55 template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ); 53 56 template< typename RefType > void handleRefType( RefType *inst, Type *other ); … … 80 83 81 84 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 82 CommonTypevisitor( type2, widenFirst, widenSecond, indexer, env, openVars );85 PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 83 86 84 87 int depth1 = type1->referenceDepth(); … … 91 94 // special case where one type has a reference depth of 1 larger than the other 92 95 if ( diff > 0 || diff < 0 ) { 96 // std::cerr << "reference depth diff: " << diff << std::endl; 93 97 Type * result = nullptr; 94 if ( ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 ) ) { 98 ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 ); 99 ReferenceType * ref2 = dynamic_cast< ReferenceType * >( type2 ); 100 if ( diff > 0 ) { 101 // deeper on the left 102 assert( ref1 ); 103 result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars ); 104 } else { 105 // deeper on the right 106 assert( ref2 ); 107 result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars ); 108 } 109 if ( result && ref1 ) { 95 110 // 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 ); 111 // std::cerr << "formal is reference; result should be reference" << std::endl; 112 result = new ReferenceType( ref1->get_qualifiers(), result ); 102 113 } 103 114 // std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl; … … 108 119 109 120 type1->accept( visitor ); 110 Type *result = visitor. get_result();121 Type *result = visitor.pass.get_result(); 111 122 if ( ! result ) { 112 123 // this appears to be handling for opaque type declarations … … 180 191 } 181 192 182 void CommonType:: visit( __attribute((unused)) VoidType *voidType) {}183 184 void CommonType:: visit( BasicType *basicType ) {193 void CommonType::postvisit( VoidType * ) {} 194 195 void CommonType::postvisit( BasicType *basicType ) { 185 196 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 186 197 BasicType::Kind newType = combinedType[ basicType->get_kind() ][ otherBasic->get_kind() ]; … … 211 222 } 212 223 213 void CommonType:: visit( PointerType *pointerType ) {224 void CommonType::postvisit( PointerType *pointerType ) { 214 225 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 215 226 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; … … 246 257 } 247 258 248 void CommonType:: visit( __attribute((unused)) ArrayType *arrayType) {}249 250 void CommonType:: visit( ReferenceType *refType ) {259 void CommonType::postvisit( ArrayType * ) {} 260 261 void CommonType::postvisit( ReferenceType *refType ) { 251 262 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 252 263 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; … … 283 294 } 284 295 285 void CommonType:: visit( __attribute((unused)) FunctionType *functionType) {}286 void CommonType:: visit( __attribute((unused)) StructInstType *aggregateUseType) {}287 void CommonType:: visit( __attribute((unused)) UnionInstType *aggregateUseType) {}288 289 void CommonType:: visit( EnumInstType *enumInstType ) {296 void CommonType::postvisit( FunctionType * ) {} 297 void CommonType::postvisit( StructInstType * ) {} 298 void CommonType::postvisit( UnionInstType * ) {} 299 300 void CommonType::postvisit( EnumInstType *enumInstType ) { 290 301 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 291 302 // reuse BasicType, EnumInstType code by swapping type2 with enumInstType 292 ValueGuard< Type * > temp( type2 ); 293 type2 = enumInstType; 294 temp.old->accept( *this ); 295 } // if 296 } 297 298 void CommonType::visit( __attribute((unused)) TraitInstType *aggregateUseType ) { 299 } 300 301 void CommonType::visit( TypeInstType *inst ) { 303 result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars ); 304 } // if 305 } 306 307 void CommonType::postvisit( TraitInstType * ) { 308 } 309 310 void CommonType::postvisit( TypeInstType *inst ) { 302 311 if ( widenFirst ) { 303 312 NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ); … … 321 330 } 322 331 323 void CommonType:: visit( __attribute((unused)) TupleType *tupleType) {}324 void CommonType:: visit( __attribute((unused)) VarArgsType *varArgsType) {}325 326 void CommonType:: visit( ZeroType *zeroType ) {332 void CommonType::postvisit( TupleType * ) {} 333 void CommonType::postvisit( VarArgsType * ) {} 334 335 void CommonType::postvisit( ZeroType *zeroType ) { 327 336 if ( widenFirst ) { 328 337 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 338 347 } 339 348 340 void CommonType:: visit( OneType *oneType ) {349 void CommonType::postvisit( OneType *oneType ) { 341 350 if ( widenFirst ) { 342 351 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { -
src/ResolvExpr/ConversionCost.cc
rb158d8f rb6838214 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
rb158d8f rb6838214 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
rb158d8f rb6838214 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 ) { … … 78 62 virtual ~MemberIterator() {} 79 63 64 /// walks the current object using the given designators as a guide 80 65 virtual void setPosition( std::list< Expression * > & designators ) = 0; 66 67 /// retrieve the list of possible Type/Designaton pairs for the current position in the currect object 81 68 virtual std::list<InitAlternative> operator*() const = 0; 69 70 /// true if the iterator is not currently at the end 82 71 virtual operator bool() const = 0; 72 73 /// moves the iterator by one member in the current object 83 74 virtual MemberIterator & bigStep() = 0; 75 76 /// moves the iterator by one member in the current subobject 84 77 virtual MemberIterator & smallStep() = 0; 78 79 /// the type of the current object 85 80 virtual Type * getType() = 0; 81 82 /// the type of the current subobject 86 83 virtual Type * getNext() = 0; 87 84 85 /// printing for debug 88 86 virtual void print( std::ostream & out, Indenter indent ) const = 0; 89 87 88 /// helper for operator*; aggregates must add designator to each init alternative, but 89 /// adding designators in operator* creates duplicates. 90 90 virtual std::list<InitAlternative> first() const = 0; // should be protected 91 91 }; … … 141 141 base = at->get_base(); 142 142 memberIter = createMemberIterator( base ); 143 if ( at->isVarLen ) throw SemanticError( "VLA initialization does not support @=", at ); 143 144 setSize( at->get_dimension() ); 144 145 } … … 151 152 void setSize( Expression * expr ) { 152 153 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 153 size = getConstValue( constExpr ); 154 PRINT( std::cerr << "array type with size: " << size << std::endl; ) 154 try { 155 size = constExpr->intValue(); 156 PRINT( std::cerr << "array type with size: " << size << std::endl; ) 157 } catch ( SemanticError & ) { 158 throw SemanticError( "Constant expression of non-integral type in array dimension: ", expr ); 159 } 155 160 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 156 161 setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast 162 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 163 if ( EnumInstType * inst = dynamic_cast< EnumInstType * > ( varExpr->result ) ) { 164 long long int value; 165 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 166 size = value; 167 } 168 } 157 169 } else { 158 170 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 176 // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions 165 177 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 166 index = getConstValue( constExpr ); 178 try { 179 index = constExpr->intValue(); 180 } catch( SemanticError & ) { 181 throw SemanticError( "Constant expression of non-integral type in array designator: ", expr ); 182 } 167 183 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 168 184 setPosition( castExpr->get_arg() ); 169 185 } 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 186 EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() ); 187 assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() ); 188 long long int value; 189 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 190 index = value; 191 } 172 192 } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) { 173 193 index = 0; // xxx - get actual sizeof/alignof value? … … 350 370 } 351 371 } 352 // if ( curMember == std::next( decl->get_members().begin(), 1 ) ) { // xxx - this never triggers because curMember is incremented immediately on construction 353 if ( atbegin ) { // xxx - this never triggers because curMember is incremented immediately on construction 372 if ( atbegin ) { 354 373 // xxx - what about case of empty struct?? 355 374 // only add self if at the very beginning of the structure … … 385 404 return *this; 386 405 } 387 virtual std::list<InitAlternative> first() const { return std::list<InitAlternative>{}; }388 406 }; 389 407 … … 439 457 return new UnionIterator( uit ); 440 458 } else { 441 assertf( dynamic_cast< TypeInstType * >( type ), "some other reftotype");459 assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() ); 442 460 return new SimpleIterator( type ); 443 461 } -
src/ResolvExpr/FindOpenVars.cc
rb158d8f rb6838214 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
rb158d8f rb6838214 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
rb158d8f rb6838214 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
rb158d8f rb6838214 14 14 // 15 15 16 #include "Common/PassVisitor.h" 16 17 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 17 18 #include "SynTree/Type.h" // for TypeInstType, Type, BasicType … … 20 21 21 22 namespace ResolvExpr { 22 class PtrsAssignable : public Visitor { 23 public: 23 struct PtrsAssignable : public WithShortCircuiting { 24 24 PtrsAssignable( Type *dest, const TypeEnvironment &env ); 25 25 26 26 int get_result() const { return result; } 27 27 28 virtual void visit( VoidType *voidType ); 29 virtual void visit( BasicType *basicType ); 30 virtual void visit( PointerType *pointerType ); 31 virtual void visit( ArrayType *arrayType ); 32 virtual void visit( FunctionType *functionType ); 33 virtual void visit( StructInstType *inst ); 34 virtual void visit( UnionInstType *inst ); 35 virtual void visit( EnumInstType *inst ); 36 virtual void visit( TraitInstType *inst ); 37 virtual void visit( TypeInstType *inst ); 38 virtual void visit( TupleType *tupleType ); 39 virtual void visit( VarArgsType *varArgsType ); 40 virtual void visit( ZeroType *zeroType ); 41 virtual void visit( OneType *oneType ); 28 void previsit( Type * ) { visit_children = false; } 29 30 void postvisit( VoidType * voidType ); 31 void postvisit( BasicType * basicType ); 32 void postvisit( PointerType * pointerType ); 33 void postvisit( ArrayType * arrayType ); 34 void postvisit( FunctionType * functionType ); 35 void postvisit( StructInstType * inst ); 36 void postvisit( UnionInstType * inst ); 37 void postvisit( EnumInstType * inst ); 38 void postvisit( TraitInstType * inst ); 39 void postvisit( TypeInstType * inst ); 40 void postvisit( TupleType * tupleType ); 41 void postvisit( VarArgsType * varArgsType ); 42 void postvisit( ZeroType * zeroType ); 43 void postvisit( OneType * oneType ); 42 44 private: 43 45 Type *dest; … … 59 61 return -1; 60 62 } else { 61 P trsAssignableptrs( dest, env );63 PassVisitor<PtrsAssignable> ptrs( dest, env ); 62 64 src->accept( ptrs ); 63 return ptrs. get_result();65 return ptrs.pass.get_result(); 64 66 } // if 65 67 } … … 67 69 PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {} 68 70 69 void PtrsAssignable:: visit( __attribute((unused)) VoidType *voidType) {71 void PtrsAssignable::postvisit( VoidType * ) { 70 72 // T * = void * is disallowed - this is a change from C, where any 71 73 // void * can be assigned or passed to a non-void pointer without a cast. 72 74 } 73 75 74 void PtrsAssignable:: visit( __attribute__((unused)) BasicType *basicType ) {}75 void PtrsAssignable:: visit( __attribute__((unused)) PointerType *pointerType ) {}76 void PtrsAssignable:: visit( __attribute__((unused)) ArrayType *arrayType ) {}77 void PtrsAssignable:: visit( __attribute__((unused)) FunctionType *functionType ) {}76 void PtrsAssignable::postvisit( __attribute__((unused)) BasicType *basicType ) {} 77 void PtrsAssignable::postvisit( __attribute__((unused)) PointerType *pointerType ) {} 78 void PtrsAssignable::postvisit( __attribute__((unused)) ArrayType *arrayType ) {} 79 void PtrsAssignable::postvisit( __attribute__((unused)) FunctionType *functionType ) {} 78 80 79 void PtrsAssignable:: visit( __attribute__((unused)) StructInstType *inst ) {}80 void PtrsAssignable:: visit( __attribute__((unused)) UnionInstType *inst ) {}81 void PtrsAssignable::postvisit( __attribute__((unused)) StructInstType *inst ) {} 82 void PtrsAssignable::postvisit( __attribute__((unused)) UnionInstType *inst ) {} 81 83 82 void PtrsAssignable:: visit( EnumInstType * ) {84 void PtrsAssignable::postvisit( EnumInstType * ) { 83 85 if ( dynamic_cast< BasicType* >( dest ) ) { 84 86 // int * = E *, etc. is safe. This isn't technically correct, as each … … 91 93 } 92 94 93 void PtrsAssignable:: visit( __attribute__((unused)) TraitInstType *inst ) {}94 void PtrsAssignable:: visit( TypeInstType *inst ) {95 void PtrsAssignable::postvisit( __attribute__((unused)) TraitInstType *inst ) {} 96 void PtrsAssignable::postvisit( TypeInstType *inst ) { 95 97 EqvClass eqvClass; 96 98 if ( env.lookup( inst->get_name(), eqvClass ) && eqvClass.type ) { … … 100 102 } 101 103 102 void PtrsAssignable:: visit( __attribute__((unused)) TupleType *tupleType ) {}103 void PtrsAssignable:: visit( __attribute__((unused)) VarArgsType *varArgsType ) {}104 void PtrsAssignable:: visit( __attribute__((unused)) ZeroType *zeroType ) {}105 void PtrsAssignable:: visit( __attribute__((unused)) OneType *oneType ) {}104 void PtrsAssignable::postvisit( __attribute__((unused)) TupleType *tupleType ) {} 105 void PtrsAssignable::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {} 106 void PtrsAssignable::postvisit( __attribute__((unused)) ZeroType *zeroType ) {} 107 void PtrsAssignable::postvisit( __attribute__((unused)) OneType *oneType ) {} 106 108 107 109 } // namespace ResolvExpr -
src/ResolvExpr/PtrsCastable.cc
rb158d8f rb6838214 14 14 // 15 15 16 #include "Common/PassVisitor.h" 16 17 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 17 18 #include "SymTab/Indexer.h" // for Indexer … … 21 22 #include "typeops.h" // for ptrsAssignable 22 23 23 24 24 namespace ResolvExpr { 25 class PtrsCastable : public Visitor{25 struct PtrsCastable : public WithShortCircuiting { 26 26 public: 27 27 PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ); … … 29 29 int get_result() const { return result; } 30 30 31 virtual void visit(VoidType *voidType); 32 virtual void visit(BasicType *basicType); 33 virtual void visit(PointerType *pointerType); 34 virtual void visit(ArrayType *arrayType); 35 virtual void visit(FunctionType *functionType); 36 virtual void visit(StructInstType *inst); 37 virtual void visit(UnionInstType *inst); 38 virtual void visit(EnumInstType *inst); 39 virtual void visit(TraitInstType *inst); 40 virtual void visit(TypeInstType *inst); 41 virtual void visit(TupleType *tupleType); 42 virtual void visit(VarArgsType *varArgsType); 43 virtual void visit(ZeroType *zeroType); 44 virtual void visit(OneType *oneType); 31 void previsit( Type * ) { visit_children = false; } 32 33 void postvisit( VoidType * voidType ); 34 void postvisit( BasicType * basicType ); 35 void postvisit( PointerType * pointerType ); 36 void postvisit( ArrayType * arrayType ); 37 void postvisit( FunctionType * functionType ); 38 void postvisit( StructInstType * inst ); 39 void postvisit( UnionInstType * inst ); 40 void postvisit( EnumInstType * inst ); 41 void postvisit( TraitInstType * inst ); 42 void postvisit( TypeInstType * inst ); 43 void postvisit( TupleType * tupleType ); 44 void postvisit( VarArgsType * varArgsType ); 45 void postvisit( ZeroType * zeroType ); 46 void postvisit( OneType * oneType ); 45 47 private: 46 48 Type *dest; … … 79 81 EqvClass eqvClass; 80 82 if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { 83 // xxx - should this be ptrsCastable? 81 84 return ptrsAssignable( src, eqvClass.type, env ); 82 85 } // if … … 85 88 return objectCast( src, env, indexer ); 86 89 } else { 87 P trsCastableptrs( dest, env, indexer );90 PassVisitor<PtrsCastable> ptrs( dest, env, indexer ); 88 91 src->accept( ptrs ); 89 return ptrs. get_result();92 return ptrs.pass.get_result(); 90 93 } // if 91 94 } … … 95 98 } 96 99 97 void PtrsCastable:: visit( VoidType * ) {100 void PtrsCastable::postvisit( VoidType * ) { 98 101 result = objectCast( dest, env, indexer ); 99 102 } 100 103 101 void PtrsCastable:: visit( BasicType * ) {104 void PtrsCastable::postvisit( BasicType * ) { 102 105 result = objectCast( dest, env, indexer ); 103 106 } 104 107 105 void PtrsCastable:: visit( PointerType * ) {108 void PtrsCastable::postvisit( PointerType * ) { 106 109 result = objectCast( dest, env, indexer ); 107 110 } 108 111 109 void PtrsCastable:: visit( ArrayType * ) {112 void PtrsCastable::postvisit( ArrayType * ) { 110 113 result = objectCast( dest, env, indexer ); 111 114 } 112 115 113 void PtrsCastable:: visit( FunctionType * ) {116 void PtrsCastable::postvisit( FunctionType * ) { 114 117 // result = -1; 115 118 result = functionCast( dest, env, indexer ); 116 119 } 117 120 118 void PtrsCastable:: visit( StructInstType * ) {121 void PtrsCastable::postvisit( StructInstType * ) { 119 122 result = objectCast( dest, env, indexer ); 120 123 } 121 124 122 void PtrsCastable:: visit( UnionInstType * ) {125 void PtrsCastable::postvisit( UnionInstType * ) { 123 126 result = objectCast( dest, env, indexer ); 124 127 } 125 128 126 void PtrsCastable:: visit( EnumInstType * ) {129 void PtrsCastable::postvisit( EnumInstType * ) { 127 130 if ( dynamic_cast< EnumInstType* >( dest ) ) { 128 131 result = 1; … … 138 141 } 139 142 140 void PtrsCastable:: visit( TraitInstType * ) {}143 void PtrsCastable::postvisit( TraitInstType * ) {} 141 144 142 void PtrsCastable:: visit(TypeInstType *inst) {145 void PtrsCastable::postvisit(TypeInstType *inst) { 143 146 //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1; 144 147 result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1; 145 148 } 146 149 147 void PtrsCastable:: visit( TupleType * ) {150 void PtrsCastable::postvisit( TupleType * ) { 148 151 result = objectCast( dest, env, indexer ); 149 152 } 150 153 151 void PtrsCastable:: visit( VarArgsType * ) {154 void PtrsCastable::postvisit( VarArgsType * ) { 152 155 result = objectCast( dest, env, indexer ); 153 156 } 154 157 155 void PtrsCastable:: visit( ZeroType * ) {158 void PtrsCastable::postvisit( ZeroType * ) { 156 159 result = objectCast( dest, env, indexer ); 157 160 } 158 161 159 void PtrsCastable:: visit( OneType * ) {162 void PtrsCastable::postvisit( OneType * ) { 160 163 result = objectCast( dest, env, indexer ); 161 164 } -
src/ResolvExpr/RenameVars.cc
rb158d8f rb6838214 19 19 #include <utility> // for pair 20 20 21 #include "Common/PassVisitor.h" 21 22 #include "Common/SemanticError.h" // for SemanticError 22 23 #include "RenameVars.h" … … 27 28 28 29 namespace ResolvExpr { 29 RenameVars global_renamer; 30 namespace { 31 struct RenameVars { 32 RenameVars(); 33 void reset(); 30 34 31 RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) { 32 mapStack.push_front( std::map< std::string, std::string >() ); 35 void previsit( TypeInstType * instType ); 36 void previsit( Type * ); 37 void postvisit( Type * ); 38 39 private: 40 int level, resetCount; 41 std::list< std::map< std::string, std::string > > mapStack; 42 }; 43 44 PassVisitor<RenameVars> global_renamer; 45 } // namespace 46 47 void renameTyVars( Type * t ) { 48 t->accept( global_renamer ); 33 49 } 34 50 35 void RenameVars::reset() { 36 level = 0; 37 resetCount++; 51 void resetTyVarRenaming() { 52 global_renamer.pass.reset(); 38 53 } 39 54 40 void RenameVars::visit( VoidType *voidType ){41 typeBefore( voidType );42 typeAfter( voidType);43 }55 namespace { 56 RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) { 57 mapStack.push_front( std::map< std::string, std::string >() ); 58 } 44 59 45 void RenameVars::visit( BasicType *basicType) {46 typeBefore( basicType );47 typeAfter( basicType );48 }60 void RenameVars::reset() { 61 level = 0; 62 resetCount++; 63 } 49 64 50 void RenameVars::visit( PointerType *pointerType ) { 51 typeBefore( pointerType ); 52 maybeAccept( pointerType->get_base(), *this ); 53 typeAfter( pointerType ); 54 } 65 void RenameVars::previsit( TypeInstType * instType ) { 66 previsit( (Type *)instType ); 67 std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name ); 68 if ( i != mapStack.front().end() ) { 69 instType->name = i->second; 70 } // if 71 } 55 72 56 void RenameVars::visit( ArrayType *arrayType ) { 57 typeBefore( arrayType ); 58 maybeAccept( arrayType->get_dimension(), *this ); 59 maybeAccept( arrayType->get_base(), *this ); 60 typeAfter( arrayType ); 61 } 73 void RenameVars::previsit( Type * type ) { 74 if ( ! type->forall.empty() ) { 75 // copies current name mapping into new mapping 76 mapStack.push_front( mapStack.front() ); 77 // renames all "forall" type names to `_${level}_${name}' 78 for ( auto td : type->forall ) { 79 std::ostringstream output; 80 output << "_" << resetCount << "_" << level << "_" << td->name; 81 std::string newname( output.str() ); 82 mapStack.front()[ td->get_name() ] = newname; 83 td->name = newname; 84 // ditto for assertion names, the next level in 85 level++; 86 // acceptAll( td->assertions, *this ); 87 } // for 88 } // if 89 } 62 90 63 void RenameVars::visit( FunctionType *functionType ) { 64 typeBefore( functionType ); 65 acceptAll( functionType->get_returnVals(), *this ); 66 acceptAll( functionType->get_parameters(), *this ); 67 typeAfter( functionType ); 68 } 69 70 void RenameVars::visit( StructInstType *aggregateUseType ) { 71 typeBefore( aggregateUseType ); 72 acceptAll( aggregateUseType->get_parameters(), *this ); 73 typeAfter( aggregateUseType ); 74 } 75 76 void RenameVars::visit( UnionInstType *aggregateUseType ) { 77 typeBefore( aggregateUseType ); 78 acceptAll( aggregateUseType->get_parameters(), *this ); 79 typeAfter( aggregateUseType ); 80 } 81 82 void RenameVars::visit( EnumInstType *aggregateUseType ) { 83 typeBefore( aggregateUseType ); 84 acceptAll( aggregateUseType->get_parameters(), *this ); 85 typeAfter( aggregateUseType ); 86 } 87 88 void RenameVars::visit( TraitInstType *aggregateUseType ) { 89 typeBefore( aggregateUseType ); 90 acceptAll( aggregateUseType->get_parameters(), *this ); 91 typeAfter( aggregateUseType ); 92 } 93 94 void RenameVars::visit( TypeInstType *instType ) { 95 typeBefore( instType ); 96 std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->get_name() ); 97 if ( i != mapStack.front().end() ) { 98 instType->set_name( i->second ); 99 } else { 100 } // if 101 acceptAll( instType->get_parameters(), *this ); 102 typeAfter( instType ); 103 } 104 105 void RenameVars::visit( TupleType *tupleType ) { 106 typeBefore( tupleType ); 107 acceptAll( tupleType->get_types(), *this ); 108 typeAfter( tupleType ); 109 } 110 111 void RenameVars::visit( VarArgsType *varArgsType ) { 112 typeBefore( varArgsType ); 113 typeAfter( varArgsType ); 114 } 115 116 void RenameVars::visit( ZeroType *zeroType ) { 117 typeBefore( zeroType ); 118 typeAfter( zeroType ); 119 } 120 121 void RenameVars::visit( OneType *oneType ) { 122 typeBefore( oneType ); 123 typeAfter( oneType ); 124 } 125 126 void RenameVars::typeBefore( Type *type ) { 127 if ( ! type->get_forall().empty() ) { 128 // copies current name mapping into new mapping 129 mapStack.push_front( mapStack.front() ); 130 // renames all "forall" type names to `_${level}_${name}' 131 for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) { 132 std::ostringstream output; 133 output << "_" << resetCount << "_" << level << "_" << (*i)->get_name(); 134 std::string newname( output.str() ); 135 mapStack.front()[ (*i)->get_name() ] = newname; 136 (*i)->set_name( newname ); 137 // ditto for assertion names, the next level in 138 level++; 139 acceptAll( (*i)->get_assertions(), *this ); 140 } // for 141 } // if 142 } 143 144 void RenameVars::typeAfter( Type *type ) { 145 // clears name mapping added by typeBefore() 146 if ( ! type->get_forall().empty() ) { 147 mapStack.pop_front(); 148 } // if 149 } 150 91 void RenameVars::postvisit( Type * type ) { 92 // clears name mapping added by typeBefore() 93 if ( ! type->forall.empty() ) { 94 mapStack.pop_front(); 95 } // if 96 } 97 } // namespace 151 98 } // namespace ResolvExpr 152 99 -
src/ResolvExpr/RenameVars.h
rb158d8f rb6838214 24 24 25 25 namespace ResolvExpr { 26 /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID 27 void renameTyVars( Type * ); 26 28 27 /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID 28 class RenameVars : public Visitor { 29 public: 30 RenameVars(); 31 void reset(); 32 private: 33 virtual void visit( VoidType *basicType ); 34 virtual void visit( BasicType *basicType ); 35 virtual void visit( PointerType *pointerType ); 36 virtual void visit( ArrayType *arrayType ); 37 virtual void visit( FunctionType *functionType ); 38 virtual void visit( StructInstType *aggregateUseType ); 39 virtual void visit( UnionInstType *aggregateUseType ); 40 virtual void visit( EnumInstType *aggregateUseType ); 41 virtual void visit( TraitInstType *aggregateUseType ); 42 virtual void visit( TypeInstType *aggregateUseType ); 43 virtual void visit( TupleType *tupleType ); 44 virtual void visit( VarArgsType *varArgsType ); 45 virtual void visit( ZeroType *zeroType ); 46 virtual void visit( OneType *oneType ); 47 48 void typeBefore( Type *type ); 49 void typeAfter( Type *type ); 50 int level, resetCount; 51 std::list< std::map< std::string, std::string > > mapStack; 52 }; 53 54 extern RenameVars global_renamer; 29 /// resets internal state of renamer to avoid overflow 30 void resetTyVarRenaming(); 55 31 } // namespace ResolvExpr 56 32 -
src/ResolvExpr/Resolver.cc
rb158d8f rb6838214 132 132 133 133 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 134 global_renamer.reset();134 resetTyVarRenaming(); 135 135 TypeEnvironment env; 136 136 Expression *newExpr = resolveInVoidContext( untyped, indexer, env ); … … 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
rb158d8f rb6838214 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 ); -
src/ResolvExpr/Unify.cc
rb158d8f rb6838214 44 44 namespace ResolvExpr { 45 45 46 class Unify : public Visitor { 47 public: 46 struct Unify : public WithShortCircuiting { 48 47 Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 49 48 50 49 bool get_result() const { return result; } 50 51 void previsit( BaseSyntaxNode * ) { visit_children = false; } 52 53 void postvisit( VoidType * voidType ); 54 void postvisit( BasicType * basicType ); 55 void postvisit( PointerType * pointerType ); 56 void postvisit( ArrayType * arrayType ); 57 void postvisit( ReferenceType * refType ); 58 void postvisit( FunctionType * functionType ); 59 void postvisit( StructInstType * aggregateUseType ); 60 void postvisit( UnionInstType * aggregateUseType ); 61 void postvisit( EnumInstType * aggregateUseType ); 62 void postvisit( TraitInstType * aggregateUseType ); 63 void postvisit( TypeInstType * aggregateUseType ); 64 void postvisit( TupleType * tupleType ); 65 void postvisit( VarArgsType * varArgsType ); 66 void postvisit( ZeroType * zeroType ); 67 void postvisit( OneType * oneType ); 68 51 69 private: 52 virtual void visit(VoidType *voidType);53 virtual void visit(BasicType *basicType);54 virtual void visit(PointerType *pointerType);55 virtual void visit(ArrayType *arrayType);56 virtual void visit(ReferenceType *refType);57 virtual void visit(FunctionType *functionType);58 virtual void visit(StructInstType *aggregateUseType);59 virtual void visit(UnionInstType *aggregateUseType);60 virtual void visit(EnumInstType *aggregateUseType);61 virtual void visit(TraitInstType *aggregateUseType);62 virtual void visit(TypeInstType *aggregateUseType);63 virtual void visit(TupleType *tupleType);64 virtual void visit(VarArgsType *varArgsType);65 virtual void visit(ZeroType *zeroType);66 virtual void visit(OneType *oneType);67 68 70 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 69 71 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); … … 325 327 result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 326 328 } else { 327 Unifycomparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );329 PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 328 330 type1->accept( comparator ); 329 result = comparator. get_result();331 result = comparator.pass.get_result(); 330 332 } // if 331 333 #ifdef DEBUG … … 404 406 } 405 407 406 void Unify:: visit( __attribute__((unused)) VoidType *voidType) {408 void Unify::postvisit( __attribute__((unused)) VoidType *voidType) { 407 409 result = dynamic_cast< VoidType* >( type2 ); 408 410 } 409 411 410 void Unify:: visit(BasicType *basicType) {412 void Unify::postvisit(BasicType *basicType) { 411 413 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 412 414 result = basicType->get_kind() == otherBasic->get_kind(); … … 436 438 } 437 439 438 void Unify:: visit(PointerType *pointerType) {440 void Unify::postvisit(PointerType *pointerType) { 439 441 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 440 442 result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 444 446 } 445 447 446 void Unify:: visit(ReferenceType *refType) {448 void Unify::postvisit(ReferenceType *refType) { 447 449 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 448 450 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 452 454 } 453 455 454 void Unify:: visit(ArrayType *arrayType) {456 void Unify::postvisit(ArrayType *arrayType) { 455 457 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 ); 456 458 // to unify, array types must both be VLA or both not VLA … … 567 569 } 568 570 569 void Unify:: visit(FunctionType *functionType) {571 void Unify::postvisit(FunctionType *functionType) { 570 572 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 571 573 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { … … 669 671 } 670 672 671 void Unify:: visit(StructInstType *structInst) {673 void Unify::postvisit(StructInstType *structInst) { 672 674 handleGenericRefType( structInst, type2 ); 673 675 } 674 676 675 void Unify:: visit(UnionInstType *unionInst) {677 void Unify::postvisit(UnionInstType *unionInst) { 676 678 handleGenericRefType( unionInst, type2 ); 677 679 } 678 680 679 void Unify:: visit(EnumInstType *enumInst) {681 void Unify::postvisit(EnumInstType *enumInst) { 680 682 handleRefType( enumInst, type2 ); 681 683 } 682 684 683 void Unify:: visit(TraitInstType *contextInst) {685 void Unify::postvisit(TraitInstType *contextInst) { 684 686 handleRefType( contextInst, type2 ); 685 687 } 686 688 687 void Unify:: visit(TypeInstType *typeInst) {689 void Unify::postvisit(TypeInstType *typeInst) { 688 690 assert( openVars.find( typeInst->get_name() ) == openVars.end() ); 689 691 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 ); … … 740 742 } 741 743 742 void Unify:: visit(TupleType *tupleType) {744 void Unify::postvisit(TupleType *tupleType) { 743 745 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 744 746 std::unique_ptr<TupleType> flat1( tupleType->clone() ); … … 757 759 } 758 760 759 void Unify:: visit( __attribute__((unused)) VarArgsType *varArgsType ) {761 void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) { 760 762 result = dynamic_cast< VarArgsType* >( type2 ); 761 763 } 762 764 763 void Unify:: visit( __attribute__((unused)) ZeroType *zeroType ) {765 void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) { 764 766 result = dynamic_cast< ZeroType* >( type2 ); 765 767 } 766 768 767 void Unify:: visit( __attribute__((unused)) OneType *oneType ) {769 void Unify::postvisit( __attribute__((unused)) OneType *oneType ) { 768 770 result = dynamic_cast< OneType* >( type2 ); 769 771 }
Note:
See TracChangeset
for help on using the changeset viewer.