Changeset 6f096d2
- Timestamp:
- Jul 12, 2019, 4:34:56 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- e3d7f9f
- Parents:
- 8fd52e90
- Location:
- src
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Expr.hpp
r8fd52e90 r6f096d2 114 114 case Params: assertf(false, "Cannot return to resnSlots from Params"); abort(); 115 115 } 116 assertf(false, "unreachable"); 116 117 } 117 118 -
src/InitTweak/InitTweak.cc
r8fd52e90 r6f096d2 318 318 virtual ~ExpanderImpl() = default; 319 319 virtual std::vector< ast::ptr< ast::Expr > > next( IndexList & indices ) = 0; 320 virtual ast::ptr< ast::Stmt > buildListInit( 320 virtual ast::ptr< ast::Stmt > buildListInit( 321 321 ast::UntypedExpr * callExpr, IndexList & indices ) = 0; 322 322 }; … … 324 324 namespace { 325 325 template< typename Out > 326 void buildCallExpr( 327 ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension, 326 void buildCallExpr( 327 ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension, 328 328 const ast::Init * init, Out & out 329 329 ) { 330 330 const CodeLocation & loc = init->location; 331 331 332 auto cond = new ast::UntypedExpr{ 332 auto cond = new ast::UntypedExpr{ 333 333 loc, new ast::NameExpr{ loc, "?<?" }, { index, dimension } }; 334 334 335 335 std::vector< ast::ptr< ast::Expr > > args = makeInitList( init ); 336 336 splice( callExpr->args, args ); … … 338 338 out.emplace_back( new ast::IfStmt{ loc, cond, new ast::ExprStmt{ loc, callExpr } } ); 339 339 340 out.emplace_back( new ast::ExprStmt{ 340 out.emplace_back( new ast::ExprStmt{ 341 341 loc, new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, "++?" }, { index } } } ); 342 342 } … … 344 344 template< typename Out > 345 345 void build( 346 ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices, 346 ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices, 347 347 const ast::Init * init, Out & out 348 348 ) { … … 371 371 372 372 static UniqueName targetLabel( "L__autogen__" ); 373 ast::Label switchLabel{ 373 ast::Label switchLabel{ 374 374 loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } }; 375 375 376 376 std::vector< ast::ptr< ast::Stmt > > branches; 377 377 for ( const ast::Init * init : *listInit ) { … … 381 381 std::vector< ast::ptr< ast::Stmt > > stmts; 382 382 build( callExpr, indices, init, stmts ); 383 stmts.emplace_back( 383 stmts.emplace_back( 384 384 new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } ); 385 385 branches.emplace_back( new ast::CaseStmt{ loc, condition, std::move( stmts ) } ); … … 398 398 return makeInitList( init ); 399 399 } 400 401 ast::ptr< ast::Stmt > buildListInit( 402 ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices 400 401 ast::ptr< ast::Stmt > buildListInit( 402 ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices 403 403 ) override { 404 // If array came with an initializer list, initialize each element. We may have more 405 // initializers than elements of the array; need to check at each index that we have 406 // not exceeded size. We may have fewer initializers than elements in the array; need 407 // to default-construct remaining elements. To accomplish this, generate switch 404 // If array came with an initializer list, initialize each element. We may have more 405 // initializers than elements of the array; need to check at each index that we have 406 // not exceeded size. We may have fewer initializers than elements in the array; need 407 // to default-construct remaining elements. To accomplish this, generate switch 408 408 // statement consuming all of expander's elements 409 409 … … 427 427 ExprImpl_new( const ast::Expr * a ) : arg( a ) {} 428 428 429 std::vector< ast::ptr< ast::Expr > > next( 430 InitExpander_new::IndexList & indices 429 std::vector< ast::ptr< ast::Expr > > next( 430 InitExpander_new::IndexList & indices 431 431 ) override { 432 432 if ( ! arg ) return {}; … … 437 437 // go through indices and layer on subscript exprs ?[?] 438 438 ++it; 439 expr = new ast::UntypedExpr{ 439 expr = new ast::UntypedExpr{ 440 440 loc, new ast::NameExpr{ loc, "?[?]" }, { expr, *it } }; 441 441 } 442 442 return { expr }; 443 443 } 444 445 ast::ptr< ast::Stmt > buildListInit( 446 ast::UntypedExpr *, InitExpander_new::IndexList & 447 ) override { 444 445 ast::ptr< ast::Stmt > buildListInit( 446 ast::UntypedExpr *, InitExpander_new::IndexList & 447 ) override { 448 448 return {}; 449 449 } … … 464 464 } 465 465 466 /// builds statement which has the same semantics as a C-style list initializer (for array 466 /// builds statement which has the same semantics as a C-style list initializer (for array 467 467 /// initializers) using callExpr as the base expression to perform initialization 468 468 ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) { … … 668 668 669 669 const ast::DeclWithType * func = getCalledFunction( appExpr->func ); 670 assertf( func, 670 assertf( func, 671 671 "getCalledFunction returned nullptr: %s", toString( appExpr->func ).c_str() ); 672 673 // check for Intrinsic only -- don't want to remove all overridable ctor/dtor because 674 // autogenerated ctor/dtor will call all member dtors, and some members may have a 672 673 // check for Intrinsic only -- don't want to remove all overridable ctor/dtor because 674 // autogenerated ctor/dtor will call all member dtors, and some members may have a 675 675 // user-defined dtor 676 676 return func->linkage == ast::Linkage::Intrinsic ? appExpr : nullptr; … … 707 707 return allofCtorDtor( stmt, []( const ast::Expr * callExpr ){ 708 708 if ( const ast::ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 709 const ast::FunctionType * funcType = 709 const ast::FunctionType * funcType = 710 710 GenPoly::getFunctionType( appExpr->func->result ); 711 711 assert( funcType ); … … 997 997 bool isCtorDtorAssign( const std::string & str ) { return isCtorDtor( str ) || isAssignment( str ); } 998 998 999 FunctionDecl * isCopyFunction(Declaration * decl, const std::string & fname ) {1000 FunctionDecl * function = dynamic_cast<FunctionDecl * >( decl );999 const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname ) { 1000 const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( decl ); 1001 1001 if ( ! function ) return nullptr; 1002 1002 if ( function->name != fname ) return nullptr; … … 1022 1022 if ( ! t1 ) return false; 1023 1023 const ast::Type * t2 = ftype->params.back()->get_type(); 1024 1024 1025 1025 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} ); 1026 1026 } 1027 1027 1028 FunctionDecl * isAssignment(Declaration * decl ) {1028 const FunctionDecl * isAssignment( const Declaration * decl ) { 1029 1029 return isCopyFunction( decl, "?=?" ); 1030 1030 } 1031 FunctionDecl * isDestructor(Declaration * decl ) {1032 if ( isDestructor( decl-> get_name()) ) {1033 return dynamic_cast< FunctionDecl * >( decl );1031 const FunctionDecl * isDestructor( const Declaration * decl ) { 1032 if ( isDestructor( decl->name ) ) { 1033 return dynamic_cast< const FunctionDecl * >( decl ); 1034 1034 } 1035 1035 return nullptr; 1036 1036 } 1037 FunctionDecl * isDefaultConstructor(Declaration * decl ) {1037 const FunctionDecl * isDefaultConstructor( const Declaration * decl ) { 1038 1038 if ( isConstructor( decl->name ) ) { 1039 if ( FunctionDecl * func = dynamic_cast<FunctionDecl * >( decl ) ) {1039 if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) { 1040 1040 if ( func->type->parameters.size() == 1 ) { 1041 1041 return func; … … 1045 1045 return nullptr; 1046 1046 } 1047 FunctionDecl * isCopyConstructor(Declaration * decl ) {1047 const FunctionDecl * isCopyConstructor( const Declaration * decl ) { 1048 1048 return isCopyFunction( decl, "?{}" ); 1049 1049 } -
src/InitTweak/InitTweak.h
r8fd52e90 r6f096d2 26 26 // helper functions for initialization 27 27 namespace InitTweak { 28 FunctionDecl * isAssignment(Declaration * decl );29 FunctionDecl * isDestructor(Declaration * decl );30 FunctionDecl * isDefaultConstructor(Declaration * decl );31 FunctionDecl * isCopyConstructor(Declaration * decl );32 FunctionDecl * isCopyFunction(Declaration * decl, const std::string & fname );28 const FunctionDecl * isAssignment( const Declaration * decl ); 29 const FunctionDecl * isDestructor( const Declaration * decl ); 30 const FunctionDecl * isDefaultConstructor( const Declaration * decl ); 31 const FunctionDecl * isCopyConstructor( const Declaration * decl ); 32 const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname ); 33 33 bool isCopyFunction( const ast::FunctionDecl * decl ); 34 34 … … 153 153 InitExpander_new & operator++ (); 154 154 155 /// builds statement which has the same semantics as a C-style list initializer (for array 156 /// initializers) using callExpr as the base expression to perform initialization. 155 /// builds statement which has the same semantics as a C-style list initializer (for array 156 /// initializers) using callExpr as the base expression to perform initialization. 157 157 /// Mutates callExpr 158 158 ast::ptr< ast::Stmt > buildListInit( ast::UntypedExpr * callExpr ); -
src/ResolvExpr/AlternativeFinder.cc
r8fd52e90 r6f096d2 336 336 } 337 337 338 if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {338 if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 339 339 addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 340 } else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {340 } else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 341 341 addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 342 342 } // if … … 344 344 345 345 template< typename StructOrUnionType > 346 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {346 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression * expr, const Alternative& alt, const Cost &newCost, const std::string & name ) { 347 347 std::list< Declaration* > members; 348 348 aggInst->lookup( name, members ); 349 349 350 350 for ( Declaration * decl : members ) { 351 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {351 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) { 352 352 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 353 353 // can't construct in place and use vector::back … … 362 362 } 363 363 364 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ) {364 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Alternative &alt, const Cost &newCost, Expression * member ) { 365 365 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 366 366 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning … … 368 368 std::string tmp; 369 369 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 370 alternatives.push_back( Alternative{ 370 alternatives.push_back( Alternative{ 371 371 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 372 372 } // if … … 374 374 } 375 375 376 void AlternativeFinder::Finder::postvisit( ApplicationExpr * applicationExpr ) {376 void AlternativeFinder::Finder::postvisit( ApplicationExpr * applicationExpr ) { 377 377 alternatives.push_back( Alternative{ applicationExpr->clone(), env } ); 378 378 } … … 475 475 } 476 476 477 // specialization cost of return types can't be accounted for directly, it disables 477 // specialization cost of return types can't be accounted for directly, it disables 478 478 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 479 479 // … … 1226 1226 // count one safe conversion for each value that is thrown away 1227 1227 thisCost.incSafe( discardedValues ); 1228 Alternative newAlt{ 1229 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), 1228 Alternative newAlt{ 1229 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), 1230 1230 alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost }; 1231 1231 inferParameters( newAlt, back_inserter( candidates ) ); … … 1328 1328 if ( sizeofExpr->get_isType() ) { 1329 1329 Type * newType = sizeofExpr->get_type()->clone(); 1330 alternatives.push_back( Alternative{ 1330 alternatives.push_back( Alternative{ 1331 1331 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1332 1332 } else { … … 1343 1343 Alternative &choice = winners.front(); 1344 1344 referenceToRvalueConversion( choice.expr, choice.cost ); 1345 alternatives.push_back( Alternative{ 1345 alternatives.push_back( Alternative{ 1346 1346 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1347 1347 } // if … … 1351 1351 if ( alignofExpr->get_isType() ) { 1352 1352 Type * newType = alignofExpr->get_type()->clone(); 1353 alternatives.push_back( Alternative{ 1353 alternatives.push_back( Alternative{ 1354 1354 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1355 1355 } else { … … 1366 1366 Alternative &choice = winners.front(); 1367 1367 referenceToRvalueConversion( choice.expr, choice.cost ); 1368 alternatives.push_back( Alternative{ 1368 alternatives.push_back( Alternative{ 1369 1369 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1370 1370 } // if … … 1377 1377 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1378 1378 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1379 alternatives.push_back( Alternative{ 1379 alternatives.push_back( Alternative{ 1380 1380 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1381 1381 renameTypes( alternatives.back().expr ); … … 1405 1405 1406 1406 namespace { 1407 void resolveAttr( SymTab::Indexer::IdData data, FunctionType *function, Type *argType, const TypeEnvironment &env, AlternativeFinder & finder ) {1407 void resolveAttr( SymTab::Indexer::IdData data, const FunctionType * function, Type * argType, const TypeEnvironment &env, AlternativeFinder & finder ) { 1408 1408 // assume no polymorphism 1409 1409 // assume no implicit conversions 1410 assert( function-> get_parameters().size() == 1 );1410 assert( function->parameters.size() == 1 ); 1411 1411 PRINT( 1412 1412 std::cerr << "resolvAttr: funcDecl is "; … … 1418 1418 const SymTab::Indexer & indexer = finder.get_indexer(); 1419 1419 AltList & alternatives = finder.get_alternatives(); 1420 if ( typesCompatibleIgnoreQualifiers( argType, function-> get_parameters().front()->get_type(), indexer, env ) ) {1420 if ( typesCompatibleIgnoreQualifiers( argType, function->parameters.front()->get_type(), indexer, env ) ) { 1421 1421 Cost cost = Cost::zero; 1422 1422 Expression * newExpr = data.combine( cost ); 1423 alternatives.push_back( Alternative{ 1424 new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, 1423 alternatives.push_back( Alternative{ 1424 new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, 1425 1425 AssertionList{}, Cost::zero, cost } ); 1426 1426 for ( DeclarationWithType * retVal : function->returnVals ) { … … 1431 1431 } 1432 1432 1433 void AlternativeFinder::Finder::postvisit( AttrExpr * attrExpr ) {1433 void AlternativeFinder::Finder::postvisit( AttrExpr * attrExpr ) { 1434 1434 // assume no 'pointer-to-attribute' 1435 NameExpr * nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );1435 NameExpr * nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() ); 1436 1436 assert( nameExpr ); 1437 1437 std::list< SymTab::Indexer::IdData > attrList; … … 1439 1439 if ( attrExpr->get_isType() || attrExpr->get_expr() ) { 1440 1440 for ( auto & data : attrList ) { 1441 DeclarationWithType * id = data.id;1441 const DeclarationWithType * id = data.id; 1442 1442 // check if the type is function 1443 if ( FunctionType *function = dynamic_cast< FunctionType* >( id->get_type() ) ) {1443 if ( const FunctionType * function = dynamic_cast< const FunctionType * >( id->get_type() ) ) { 1444 1444 // assume exactly one parameter 1445 if ( function-> get_parameters().size() == 1 ) {1445 if ( function->parameters.size() == 1 ) { 1446 1446 if ( attrExpr->get_isType() ) { 1447 1447 resolveAttr( data, function, attrExpr->get_type(), env, altFinder); … … 1462 1462 Cost cost = Cost::zero; 1463 1463 Expression * newExpr = data.combine( cost ); 1464 alternatives.push_back( Alternative{ 1464 alternatives.push_back( Alternative{ 1465 1465 newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } ); 1466 1466 renameTypes( alternatives.back().expr ); … … 1469 1469 } 1470 1470 1471 void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) {1471 void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) { 1472 1472 AlternativeFinder firstFinder( indexer, env ); 1473 1473 firstFinder.findWithAdjustment( logicalExpr->get_arg1() ); … … 1486 1486 cloneAll( second.need, need ); 1487 1487 1488 LogicalExpr *newExpr = new LogicalExpr{ 1488 LogicalExpr *newExpr = new LogicalExpr{ 1489 1489 first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() }; 1490 alternatives.push_back( Alternative{ 1491 newExpr, std::move(compositeEnv), std::move(openVars), 1490 alternatives.push_back( Alternative{ 1491 newExpr, std::move(compositeEnv), std::move(openVars), 1492 1492 AssertionList( need.begin(), need.end() ), first.cost + second.cost } ); 1493 1493 } … … 1522 1522 cloneAll( third.need, need ); 1523 1523 AssertionSet have; 1524 1524 1525 1525 // unify true and false types, then infer parameters to produce new alternatives 1526 1526 Type* commonType = nullptr; 1527 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1527 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1528 1528 need, have, openVars, indexer, commonType ) ) { 1529 ConditionalExpr *newExpr = new ConditionalExpr{ 1529 ConditionalExpr *newExpr = new ConditionalExpr{ 1530 1530 first.expr->clone(), second.expr->clone(), third.expr->clone() }; 1531 1531 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1532 1532 // convert both options to the conditional result type 1533 1533 Cost cost = first.cost + second.cost + third.cost; 1534 cost += computeExpressionConversionCost( 1534 cost += computeExpressionConversionCost( 1535 1535 newExpr->arg2, newExpr->result, indexer, compositeEnv ); 1536 cost += computeExpressionConversionCost( 1536 cost += computeExpressionConversionCost( 1537 1537 newExpr->arg3, newExpr->result, indexer, compositeEnv ); 1538 1538 // output alternative 1539 Alternative newAlt{ 1540 newExpr, std::move(compositeEnv), std::move(openVars), 1539 Alternative newAlt{ 1540 newExpr, std::move(compositeEnv), std::move(openVars), 1541 1541 AssertionList( need.begin(), need.end() ), cost }; 1542 1542 inferParameters( newAlt, back_inserter( alternatives ) ); … … 1553 1553 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1554 1554 for ( const Alternative & alt : secondFinder.alternatives ) { 1555 alternatives.push_back( Alternative{ 1555 alternatives.push_back( Alternative{ 1556 1556 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1557 1557 } // for … … 1579 1579 1580 1580 Type* commonType = nullptr; 1581 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 1581 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 1582 1582 openVars, indexer, commonType ) ) { 1583 RangeExpr * newExpr = 1583 RangeExpr * newExpr = 1584 1584 new RangeExpr{ first.expr->clone(), second.expr->clone() }; 1585 1585 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1586 Alternative newAlt{ 1587 newExpr, std::move(compositeEnv), std::move(openVars), 1586 Alternative newAlt{ 1587 newExpr, std::move(compositeEnv), std::move(openVars), 1588 1588 AssertionList( need.begin(), need.end() ), first.cost + second.cost }; 1589 1589 inferParameters( newAlt, back_inserter( alternatives ) ); … … 1612 1612 cloneAll( alt.need, need ); 1613 1613 } 1614 1615 alternatives.push_back( Alternative{ 1616 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 1614 1615 alternatives.push_back( Alternative{ 1616 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 1617 1617 AssertionList( need.begin(), need.end() ), sumCost( alts ) } ); 1618 1618 } // for … … 1633 1633 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1634 1634 for ( Alternative & alt : finder.alternatives ) { 1635 alternatives.push_back( Alternative{ 1635 alternatives.push_back( Alternative{ 1636 1636 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1637 1637 } … … 1685 1685 cloneAll( alt.need, need ); 1686 1686 AssertionSet have; 1687 OpenVarSet openVars( alt.openVars ); 1688 // xxx - find things in env that don't have a "representative type" and claim 1687 OpenVarSet openVars( alt.openVars ); 1688 // xxx - find things in env that don't have a "representative type" and claim 1689 1689 // those are open vars? 1690 1690 PRINT( 1691 1691 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1692 1692 ) 1693 // It's possible that a cast can throw away some values in a multiply-valued 1694 // expression. (An example is a cast-to-void, which casts from one value to 1695 // zero.) Figure out the prefix of the subexpression results that are cast 1696 // directly. The candidate is invalid if it has fewer results than there are 1693 // It's possible that a cast can throw away some values in a multiply-valued 1694 // expression. (An example is a cast-to-void, which casts from one value to 1695 // zero.) Figure out the prefix of the subexpression results that are cast 1696 // directly. The candidate is invalid if it has fewer results than there are 1697 1697 // types to cast to. 1698 1698 int discardedValues = alt.expr->result->size() - toType->size(); 1699 1699 if ( discardedValues < 0 ) continue; 1700 // xxx - may need to go into tuple types and extract relevant types and use 1701 // unifyList. Note that currently, this does not allow casting a tuple to an 1700 // xxx - may need to go into tuple types and extract relevant types and use 1701 // unifyList. Note that currently, this does not allow casting a tuple to an 1702 1702 // atomic type (e.g. (int)([1, 2, 3])) 1703 1703 1704 1704 // unification run for side-effects 1705 1705 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); … … 1710 1710 // count one safe conversion for each value that is thrown away 1711 1711 thisCost.incSafe( discardedValues ); 1712 Alternative newAlt{ 1713 new InitExpr{ 1714 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1715 std::move(newEnv), std::move(openVars), 1712 Alternative newAlt{ 1713 new InitExpr{ 1714 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1715 std::move(newEnv), std::move(openVars), 1716 1716 AssertionList( need.begin(), need.end() ), alt.cost, thisCost }; 1717 1717 inferParameters( newAlt, back_inserter( candidates ) ); -
src/ResolvExpr/ResolveAssertions.cc
r8fd52e90 r6f096d2 197 197 } 198 198 if ( i == b.size() /* && i < a.size() */ ) return 1; 199 199 200 200 int c = a[i].compare( b[i] ); 201 201 if ( c != 0 ) return c; … … 220 220 221 221 /// Initial resolution state for an alternative 222 ResnState( Alternative & a, SymTab::Indexer& indexer )222 ResnState( Alternative & a, SymTab::Indexer & indexer ) 223 223 : alt(a), need(), newNeed(), deferred(), inferred(), costs{ Cost::zero }, indexer(indexer) { 224 224 need.swap( a.need ); … … 226 226 227 227 /// Updated resolution state with new need-list 228 ResnState( ResnState && o, IterateFlag )228 ResnState( ResnState && o, IterateFlag ) 229 229 : alt(std::move(o.alt)), need(o.newNeed.begin(), o.newNeed.end()), newNeed(), deferred(), 230 230 inferred(std::move(o.inferred)), costs(o.costs), indexer(o.indexer) { … … 234 234 235 235 /// Binds a single assertion, updating resolution state 236 void bindAssertion( const DeclarationWithType * decl, AssertionSetValue info, Alternative& alt,237 AssnCandidate & match, InferCache& inferred ) {238 239 DeclarationWithType* candidate = match.cdata.id;240 assertf( candidate-> get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );241 242 Expression * varExpr = match.cdata.combine( alt.cvtCost );236 void bindAssertion( const DeclarationWithType * decl, AssertionSetValue info, Alternative & alt, 237 AssnCandidate & match, InferCache & inferred ) { 238 239 const DeclarationWithType * candidate = match.cdata.id; 240 assertf( candidate->uniqueId, "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 241 242 Expression * varExpr = match.cdata.combine( alt.cvtCost ); 243 243 delete varExpr->result; 244 244 varExpr->result = match.adjType->clone(); … … 247 247 // place newly-inferred assertion in proper place in cache 248 248 inferred[ info.resnSlot ][ decl->get_uniqueId() ] = ParamEntry{ 249 candidate-> get_uniqueId(), candidate->clone(), match.adjType->clone(), decl->get_type()->clone(),249 candidate->uniqueId, candidate->clone(), match.adjType->clone(), decl->get_type()->clone(), 250 250 varExpr }; 251 251 } 252 252 253 253 /// Adds a captured assertion to the symbol table 254 void addToIndexer( AssertionSet & assertSet, SymTab::Indexer &indexer ) {254 void addToIndexer( AssertionSet & assertSet, SymTab::Indexer & indexer ) { 255 255 for ( auto& i : assertSet ) { 256 256 if ( i.second.isUsed ) { … … 264 264 265 265 /// Resolve a single assertion, in context 266 bool resolveAssertion( AssertionItem & assn, ResnState& resn ) {266 bool resolveAssertion( AssertionItem & assn, ResnState & resn ) { 267 267 // skip unused assertions 268 268 if ( ! assn.info.isUsed ) return true; … … 274 274 // find the candidates that unify with the desired type 275 275 CandidateList matches; 276 for ( const auto & cdata : candidates ) {277 DeclarationWithType* candidate = cdata.id;276 for ( const auto & cdata : candidates ) { 277 const DeclarationWithType * candidate = cdata.id; 278 278 279 279 // build independent unification context for candidate … … 281 281 TypeEnvironment newEnv{ resn.alt.env }; 282 282 OpenVarSet newOpenVars{ resn.alt.openVars }; 283 Type * adjType = candidate->get_type()->clone();283 Type * adjType = candidate->get_type()->clone(); 284 284 adjustExprType( adjType, newEnv, resn.indexer ); 285 285 renameTyVars( adjType ); … … 370 370 return resKey; 371 371 } 372 373 /// Replace resnSlots with inferParams and add alternative to output list, if meets pruning 372 373 /// Replace resnSlots with inferParams and add alternative to output list, if meets pruning 374 374 /// threshold. 375 375 void finalizeAssertions( ResnState& resn, PruneMap & pruneThresholds, AltList& out ) { … … 406 406 ResnList resns{ ResnState{ alt, root_indexer } }; 407 407 ResnList new_resns{}; 408 408 409 409 // Pruning thresholds by result type of the output alternatives. 410 410 // Alternatives *should* be generated in sorted order, so no need to retroactively prune -
src/ResolvExpr/Unify.cc
r8fd52e90 r6f096d2 102 102 WidenMode widen, const ast::SymbolTable & symtab ); 103 103 104 bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {104 bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 105 105 TypeEnvironment newEnv; 106 106 OpenVarSet openVars, closedVars; // added closedVars 107 107 AssertionSet needAssertions, haveAssertions; 108 Type * newFirst = first->clone(), *newSecond = second->clone();108 Type * newFirst = first->clone(), * newSecond = second->clone(); 109 109 env.apply( newFirst ); 110 110 env.apply( newSecond ); -
src/ResolvExpr/typeops.h
r8fd52e90 r6f096d2 28 28 #include "SynTree/SynTree.h" 29 29 #include "SynTree/Type.h" 30 #include "SymTab/Indexer.h" 30 31 namespace SymTab { 32 class Indexer; 33 } 31 34 32 35 namespace ResolvExpr { … … 60 63 // in AdjustExprType.cc 61 64 /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function 62 void adjustExprType( Type *& type, const TypeEnvironment &env, const SymTab::Indexer &indexer );65 void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer ); 63 66 64 67 /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer … … 66 69 67 70 template< typename ForwardIterator > 68 void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {71 void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) { 69 72 while ( begin != end ) { 70 73 adjustExprType( *begin++, env, indexer ); … … 77 80 78 81 // in CastCost.cc 79 Cost castCost( const Type * src, const Type * dest, const SymTab::Indexer & indexer, const TypeEnvironment &env );82 Cost castCost( const Type * src, const Type * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 80 83 Cost castCost( 81 84 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, … … 83 86 84 87 // in ConversionCost.cc 85 Cost conversionCost( const Type * src, const Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );88 Cost conversionCost( const Type * src, const Type * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 86 89 Cost conversionCost( 87 90 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, … … 89 92 90 93 // in AlternativeFinder.cc 91 Cost computeConversionCost( Type * actualType, Type *formalType,92 const SymTab::Indexer & indexer, const TypeEnvironment &env );94 Cost computeConversionCost( Type * actualType, Type * formalType, 95 const SymTab::Indexer & indexer, const TypeEnvironment & env ); 93 96 94 97 // in PtrsAssignable.cc 95 int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment & env );98 int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment & env ); 96 99 int ptrsAssignable( const ast::Type * src, const ast::Type * dst, 97 100 const ast::TypeEnvironment & env ); 98 101 99 102 // in PtrsCastable.cc 100 int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment & env, const SymTab::Indexer &indexer );103 int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment & env, const SymTab::Indexer & indexer ); 101 104 int ptrsCastable( 102 105 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, … … 104 107 105 108 // in Unify.cc 106 bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );107 bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment &env );108 109 inline bool typesCompatible( Type *t1, Type *t2, const SymTab::Indexer &indexer ) {109 bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 110 bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env ); 111 112 inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) { 110 113 TypeEnvironment env; 111 114 return typesCompatible( t1, t2, indexer, env ); 112 115 } 113 116 114 inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {117 inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) { 115 118 TypeEnvironment env; 116 119 return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env ); … … 131 134 132 135 // in CommonType.cc 133 Type * commonType( Type * type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );136 Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars ); 134 137 ast::ptr< ast::Type > commonType( 135 138 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen, … … 137 140 138 141 // in PolyCost.cc 139 int polyCost( Type * type, const TypeEnvironment &env, const SymTab::Indexer &indexer );142 int polyCost( Type * type, const TypeEnvironment & env, const SymTab::Indexer & indexer ); 140 143 int polyCost( 141 144 const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ); 142 145 143 146 // in SpecCost.cc 144 int specCost( Type * type );147 int specCost( Type * type ); 145 148 int specCost( const ast::Type * type ); 146 149 147 150 // in Occurs.cc 148 bool occurs( Type * type, std::string varName, const TypeEnvironment &env );151 bool occurs( Type * type, std::string varName, const TypeEnvironment & env ); 149 152 // new AST version in TypeEnvironment.cpp (only place it was used in old AST) 150 153 151 154 template<typename Iter> 152 bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment & env ) {155 bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment & env ) { 153 156 while ( begin != end ) { 154 157 if ( occurs( ty, *begin, env ) ) return true; … … 197 200 198 201 // in TypeEnvironment.cc 199 bool isFtype( Type * type );202 bool isFtype( Type * type ); 200 203 } // namespace ResolvExpr 201 204 -
src/SymTab/Indexer.cc
r8fd52e90 r6f096d2 188 188 } 189 189 190 bool isFunction( DeclarationWithType * decl ) {190 bool isFunction( const DeclarationWithType * decl ) { 191 191 return GenPoly::getFunctionType( decl->get_type() ); 192 192 } 193 193 194 bool isObject( DeclarationWithType * decl ) {194 bool isObject( const DeclarationWithType * decl ) { 195 195 return ! isFunction( decl ); 196 196 } 197 197 198 bool isDefinition( DeclarationWithType * decl ) {199 if ( FunctionDecl * func = dynamic_cast<FunctionDecl * >( decl ) ) {198 bool isDefinition( const DeclarationWithType * decl ) { 199 if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) { 200 200 // a function is a definition if it has a body 201 201 return func->statements; … … 209 209 210 210 bool Indexer::addedIdConflicts( 211 const Indexer::IdData & existing, DeclarationWithType * added,212 Indexer::OnConflict handleConflicts, BaseSyntaxNode * deleteStmt ) {211 const Indexer::IdData & existing, const DeclarationWithType * added, 212 Indexer::OnConflict handleConflicts, const BaseSyntaxNode * deleteStmt ) { 213 213 // if we're giving the same name mangling to things of different types then there is 214 214 // something wrong … … 274 274 } 275 275 276 bool Indexer::hasIncompatibleCDecl( 277 const std::string & id, const std::string &mangleName ) const { 276 bool Indexer::hasIncompatibleCDecl(const std::string & id, const std::string &mangleName ) const { 278 277 if ( ! idTable ) return false; 279 278 … … 295 294 296 295 /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function 297 std::string getOtypeKey( FunctionDecl * function ) {296 std::string getOtypeKey( const FunctionDecl * function ) { 298 297 auto& params = function->type->parameters; 299 298 assert( ! params.empty() ); … … 306 305 /// gets the declaration for the function acting on a type specified by otype key, 307 306 /// nullptr if none such 308 FunctionDecl * getFunctionForOtype(DeclarationWithType * decl, const std::string& otypeKey ) {309 FunctionDecl * func = dynamic_cast<FunctionDecl * >( decl );307 const FunctionDecl * getFunctionForOtype( const DeclarationWithType * decl, const std::string& otypeKey ) { 308 const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ); 310 309 if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr; 311 310 return func; 312 311 } 313 312 314 bool Indexer::removeSpecialOverrides( 315 Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) { 313 bool Indexer::removeSpecialOverrides(Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) { 316 314 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which 317 315 // determinethe set of ctor/dtor/assign that can be used by the requester. In particular, … … 324 322 325 323 // only relevant on function declarations 326 FunctionDecl * function = dynamic_cast<FunctionDecl * >( data.id );324 const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( data.id ); 327 325 if ( ! function ) return true; 328 326 // only need to perform this check for constructors, destructors, and assignment functions … … 343 341 for ( const auto& entry : * mangleTable ) { 344 342 // skip decls that aren't functions or are for the wrong type 345 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );343 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 346 344 if ( ! decl ) continue; 347 345 … … 382 380 for ( const auto& entry : * mangleTable ) { 383 381 // skip decls that aren't functions or are for the wrong type 384 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );382 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 385 383 if ( ! decl ) continue; 386 384 … … 410 408 for ( const auto& entry : * mangleTable ) { 411 409 // skip decls that aren't functions or are for the wrong type 412 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );410 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 413 411 if ( ! decl ) continue; 414 412 … … 433 431 } 434 432 435 void Indexer::addId( 436 DeclarationWithType * decl, OnConflict handleConflicts, Expression * baseExpr, 437 BaseSyntaxNode * deleteStmt ) { 433 void Indexer::addId(const DeclarationWithType * decl, OnConflict handleConflicts, const Expression * baseExpr, 434 const BaseSyntaxNode * deleteStmt ) { 438 435 ++* stats().add_calls; 439 436 const std::string &name = decl->name; … … 508 505 } 509 506 510 void Indexer::addId( DeclarationWithType * decl,Expression * baseExpr ) {507 void Indexer::addId( const DeclarationWithType * decl, const Expression * baseExpr ) { 511 508 // default handling of conflicts is to raise an error 512 509 addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr ); 513 510 } 514 511 515 void Indexer::addDeletedId( DeclarationWithType * decl,BaseSyntaxNode * deleteStmt ) {512 void Indexer::addDeletedId( const DeclarationWithType * decl, const BaseSyntaxNode * deleteStmt ) { 516 513 // default handling of conflicts is to raise an error 517 514 addId( decl, OnConflict::error(), nullptr, deleteStmt ); 518 515 } 519 516 520 bool addedTypeConflicts( NamedTypeDecl * existing,NamedTypeDecl * added ) {517 bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) { 521 518 if ( existing->base == nullptr ) { 522 519 return false; … … 535 532 } 536 533 537 void Indexer::addType( NamedTypeDecl * decl ) {534 void Indexer::addType( const NamedTypeDecl * decl ) { 538 535 ++* stats().add_calls; 539 536 const std::string & id = decl->name; … … 554 551 } 555 552 556 bool addedDeclConflicts( AggregateDecl * existing,AggregateDecl * added ) {553 bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) { 557 554 if ( ! existing->body ) { 558 555 return false; … … 567 564 } 568 565 569 void Indexer::addStruct( StructDecl * decl ) {566 void Indexer::addStruct( const StructDecl * decl ) { 570 567 ++* stats().add_calls; 571 568 const std::string & id = decl->name; … … 586 583 } 587 584 588 void Indexer::addEnum( EnumDecl * decl ) {585 void Indexer::addEnum( const EnumDecl * decl ) { 589 586 ++* stats().add_calls; 590 587 const std::string & id = decl->name; … … 609 606 } 610 607 611 void Indexer::addUnion( UnionDecl * decl ) {608 void Indexer::addUnion( const UnionDecl * decl ) { 612 609 ++* stats().add_calls; 613 610 const std::string & id = decl->name; … … 628 625 } 629 626 630 void Indexer::addTrait( TraitDecl * decl ) {627 void Indexer::addTrait( const TraitDecl * decl ) { 631 628 ++* stats().add_calls; 632 629 const std::string & id = decl->name; … … 647 644 } 648 645 649 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, 650 OnConflict handleConflicts ) { 646 void Indexer::addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ) { 651 647 for ( Declaration * decl : aggr->members ) { 652 648 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { 653 649 addId( dwt, handleConflicts, expr ); 654 650 if ( dwt->name == "" ) { 655 Type * t = dwt->get_type()->stripReferences();656 if ( dynamic_cast< StructInstType *>( t ) || dynamic_cast<UnionInstType *>( t ) ) {651 const Type * t = dwt->get_type()->stripReferences(); 652 if ( dynamic_cast<const StructInstType *>( t ) || dynamic_cast<const UnionInstType *>( t ) ) { 657 653 Expression * base = expr->clone(); 658 654 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost? … … 665 661 } 666 662 667 void Indexer::addWith( std::list< Expression * > & withExprs,BaseSyntaxNode * withStmt ) {668 for ( Expression * expr : withExprs ) {663 void Indexer::addWith( const std::list< Expression * > & withExprs, const BaseSyntaxNode * withStmt ) { 664 for ( const Expression * expr : withExprs ) { 669 665 if ( expr->result ) { 670 666 AggregateDecl * aggr = expr->result->stripReferences()->getAggr(); … … 689 685 } 690 686 691 void Indexer::addFunctionType( FunctionType * ftype ) {687 void Indexer::addFunctionType( const FunctionType * ftype ) { 692 688 addTypes( ftype->forall ); 693 689 addIds( ftype->returnVals ); … … 700 696 Expression * base = baseExpr->clone(); 701 697 ResolvExpr::referenceToRvalueConversion( base, cost ); 702 ret = new MemberExpr( id, base );698 ret = new MemberExpr( const_cast<DeclarationWithType *>(id), base ); 703 699 // xxx - this introduces hidden environments, for now remove them. 704 700 // std::swap( base->env, ret->env ); … … 706 702 base->env = nullptr; 707 703 } else { 708 ret = new VariableExpr( id);709 } 710 if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt);704 ret = new VariableExpr( const_cast<DeclarationWithType *>(id) ); 705 } 706 if ( deleteStmt ) ret = new DeletedExpr( ret, const_cast<BaseSyntaxNode *>(deleteStmt) ); 711 707 return ret; 712 708 } -
src/SymTab/Indexer.h
r8fd52e90 r6f096d2 40 40 41 41 struct IdData { 42 DeclarationWithType * id = nullptr;43 Expression * baseExpr = nullptr; // WithExpr42 const DeclarationWithType * id = nullptr; 43 const Expression * baseExpr = nullptr; // WithExpr 44 44 45 45 /// non-null if this declaration is deleted 46 BaseSyntaxNode * deleteStmt = nullptr;46 const BaseSyntaxNode * deleteStmt = nullptr; 47 47 /// scope of identifier 48 48 unsigned long scope = 0; … … 51 51 IdData() = default; 52 52 IdData( 53 DeclarationWithType * id, Expression * baseExpr,BaseSyntaxNode * deleteStmt,53 const DeclarationWithType * id, const Expression * baseExpr, const BaseSyntaxNode * deleteStmt, 54 54 unsigned long scope ) 55 55 : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ), scope( scope ) {} 56 IdData( const IdData& o, BaseSyntaxNode * deleteStmt )56 IdData( const IdData& o, const BaseSyntaxNode * deleteStmt ) 57 57 : id( o.id ), baseExpr( o.baseExpr ), deleteStmt( deleteStmt ), scope( o.scope ) {} 58 58 … … 82 82 const EnumDecl * globalLookupEnum( const std::string & id ) const; 83 83 84 void addId( DeclarationWithType * decl,Expression * baseExpr = nullptr );85 void addDeletedId( DeclarationWithType * decl,BaseSyntaxNode * deleteStmt );84 void addId( const DeclarationWithType * decl, const Expression * baseExpr = nullptr ); 85 void addDeletedId( const DeclarationWithType * decl, const BaseSyntaxNode * deleteStmt ); 86 86 87 void addType( NamedTypeDecl * decl );87 void addType( const NamedTypeDecl * decl ); 88 88 void addStruct( const std::string & id ); 89 void addStruct( StructDecl * decl );90 void addEnum( EnumDecl * decl );89 void addStruct( const StructDecl * decl ); 90 void addEnum( const EnumDecl * decl ); 91 91 void addUnion( const std::string & id ); 92 void addUnion( UnionDecl * decl );93 void addTrait( TraitDecl * decl );92 void addUnion( const UnionDecl * decl ); 93 void addTrait( const TraitDecl * decl ); 94 94 95 95 /// adds all of the IDs from WithStmt exprs 96 void addWith( std::list< Expression * > & withExprs,BaseSyntaxNode * withStmt );96 void addWith( const std::list< Expression * > & withExprs, const BaseSyntaxNode * withStmt ); 97 97 98 98 /// convenience function for adding a list of Ids to the indexer … … 103 103 104 104 /// convenience function for adding all of the declarations in a function type to the indexer 105 void addFunctionType( FunctionType * ftype );105 void addFunctionType( const FunctionType * ftype ); 106 106 107 107 private: … … 109 109 template<typename Decl> 110 110 struct Scoped { 111 Decl * decl; ///< declaration111 const Decl * decl; ///< declaration 112 112 unsigned long scope; ///< scope of this declaration 113 113 114 Scoped( Decl * d, unsigned long s) : decl(d), scope(s) {}114 Scoped(const Decl * d, unsigned long s) : decl(d), scope(s) {} 115 115 }; 116 116 … … 144 144 /// Removes matching autogenerated constructors and destructors so that they will not be 145 145 /// selected. If returns false, passed decl should not be added. 146 bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr& mangleTable );146 bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable ); 147 147 148 148 /// Options for handling identifier conflicts … … 152 152 Delete ///< Delete the earlier version with the delete statement 153 153 } mode; 154 BaseSyntaxNode * deleteStmt; ///< Statement that deletes this expression154 const BaseSyntaxNode * deleteStmt; ///< Statement that deletes this expression 155 155 156 156 private: 157 157 OnConflict() : mode(Error), deleteStmt(nullptr) {} 158 OnConflict( BaseSyntaxNode * d ) : mode(Delete), deleteStmt(d) {}158 OnConflict( const BaseSyntaxNode * d ) : mode(Delete), deleteStmt(d) {} 159 159 public: 160 160 OnConflict( const OnConflict& ) = default; 161 161 162 162 static OnConflict error() { return {}; } 163 static OnConflict deleteWith( BaseSyntaxNode * d ) { return { d }; }163 static OnConflict deleteWith( const BaseSyntaxNode * d ) { return { d }; } 164 164 }; 165 165 166 166 /// true if the existing identifier conflicts with the added identifier 167 167 bool addedIdConflicts( 168 const IdData & existing,DeclarationWithType * added, OnConflict handleConflicts,169 BaseSyntaxNode * deleteStmt );168 const IdData & existing, const DeclarationWithType * added, OnConflict handleConflicts, 169 const BaseSyntaxNode * deleteStmt ); 170 170 171 171 /// common code for addId, addDeletedId, etc. 172 void addId( 173 DeclarationWithType * decl, OnConflict handleConflicts, 174 Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr ); 172 void addId(const DeclarationWithType * decl, OnConflict handleConflicts, 173 const Expression * baseExpr = nullptr, const BaseSyntaxNode * deleteStmt = nullptr ); 175 174 176 175 /// adds all of the members of the Aggregate (addWith helper) 177 void addMembers( AggregateDecl * aggr,Expression * expr, OnConflict handleConflicts );176 void addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ); 178 177 179 178 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name 180 bool hasCompatibleCDecl( const std::string & id, const std::string & mangleName ) const;179 bool hasCompatibleCDecl( const std::string & id, const std::string & mangleName ) const; 181 180 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name 182 bool hasIncompatibleCDecl( const std::string & id, const std::string & mangleName ) const;181 bool hasIncompatibleCDecl( const std::string & id, const std::string & mangleName ) const; 183 182 }; 184 183 } // namespace SymTab -
src/SymTab/Mangler.cc
r8fd52e90 r6f096d2 42 42 Mangler_old( const Mangler_old & ) = delete; 43 43 44 void previsit( BaseSyntaxNode * ) { visit_children = false; }45 46 void postvisit( ObjectDecl * declaration );47 void postvisit( FunctionDecl * declaration );48 void postvisit( TypeDecl * declaration );49 50 void postvisit( VoidType * voidType );51 void postvisit( BasicType * basicType );52 void postvisit( PointerType * pointerType );53 void postvisit( ArrayType * arrayType );54 void postvisit( ReferenceType * refType );55 void postvisit( FunctionType * functionType );56 void postvisit( StructInstType * aggregateUseType );57 void postvisit( UnionInstType * aggregateUseType );58 void postvisit( EnumInstType * aggregateUseType );59 void postvisit( TypeInstType * aggregateUseType );60 void postvisit( TraitInstType * inst );61 void postvisit( TupleType * tupleType );62 void postvisit( VarArgsType * varArgsType );63 void postvisit( ZeroType * zeroType );64 void postvisit( OneType * oneType );65 void postvisit( QualifiedType * qualType );44 void previsit( const BaseSyntaxNode * ) { visit_children = false; } 45 46 void postvisit( const ObjectDecl * declaration ); 47 void postvisit( const FunctionDecl * declaration ); 48 void postvisit( const TypeDecl * declaration ); 49 50 void postvisit( const VoidType * voidType ); 51 void postvisit( const BasicType * basicType ); 52 void postvisit( const PointerType * pointerType ); 53 void postvisit( const ArrayType * arrayType ); 54 void postvisit( const ReferenceType * refType ); 55 void postvisit( const FunctionType * functionType ); 56 void postvisit( const StructInstType * aggregateUseType ); 57 void postvisit( const UnionInstType * aggregateUseType ); 58 void postvisit( const EnumInstType * aggregateUseType ); 59 void postvisit( const TypeInstType * aggregateUseType ); 60 void postvisit( const TraitInstType * inst ); 61 void postvisit( const TupleType * tupleType ); 62 void postvisit( const VarArgsType * varArgsType ); 63 void postvisit( const ZeroType * zeroType ); 64 void postvisit( const OneType * oneType ); 65 void postvisit( const QualifiedType * qualType ); 66 66 67 67 std::string get_mangleName() { return mangleName.str(); } … … 79 79 80 80 public: 81 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 81 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 82 82 int nextVarNum, const VarMapType& varNums ); 83 83 84 84 private: 85 void mangleDecl( DeclarationWithType *declaration );86 void mangleRef( ReferenceToType *refType, std::string prefix );87 88 void printQualifiers( Type *type );85 void mangleDecl( const DeclarationWithType * declaration ); 86 void mangleRef( const ReferenceToType * refType, std::string prefix ); 87 88 void printQualifiers( const Type *type ); 89 89 }; // Mangler_old 90 90 } // namespace 91 91 92 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {92 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) { 93 93 PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams ); 94 94 maybeAccept( decl, mangler ); … … 96 96 } 97 97 98 std::string mangleType( Type * ty ) {98 std::string mangleType( const Type * ty ) { 99 99 PassVisitor<Mangler_old> mangler( false, true, true ); 100 100 maybeAccept( ty, mangler ); … … 102 102 } 103 103 104 std::string mangleConcrete( Type * ty ) {104 std::string mangleConcrete( const Type * ty ) { 105 105 PassVisitor<Mangler_old> mangler( false, false, false ); 106 106 maybeAccept( ty, mangler ); … … 110 110 namespace { 111 111 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams ) 112 : nextVarNum( 0 ), isTopLevel( true ), 113 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 112 : nextVarNum( 0 ), isTopLevel( true ), 113 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 114 114 mangleGenericParams( mangleGenericParams ) {} 115 116 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 115 116 Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 117 117 int nextVarNum, const VarMapType& varNums ) 118 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 119 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 118 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 119 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 120 120 mangleGenericParams( mangleGenericParams ) {} 121 121 122 void Mangler_old::mangleDecl( DeclarationWithType * declaration ) {122 void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) { 123 123 bool wasTopLevel = isTopLevel; 124 124 if ( isTopLevel ) { … … 150 150 } 151 151 152 void Mangler_old::postvisit( ObjectDecl * declaration ) {152 void Mangler_old::postvisit( const ObjectDecl * declaration ) { 153 153 mangleDecl( declaration ); 154 154 } 155 155 156 void Mangler_old::postvisit( FunctionDecl * declaration ) {156 void Mangler_old::postvisit( const FunctionDecl * declaration ) { 157 157 mangleDecl( declaration ); 158 158 } 159 159 160 void Mangler_old::postvisit( VoidType * voidType ) {160 void Mangler_old::postvisit( const VoidType * voidType ) { 161 161 printQualifiers( voidType ); 162 162 mangleName << Encoding::void_t; 163 163 } 164 164 165 void Mangler_old::postvisit( BasicType * basicType ) {165 void Mangler_old::postvisit( const BasicType * basicType ) { 166 166 printQualifiers( basicType ); 167 assertf( basicType-> get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind());168 mangleName << Encoding::basicTypes[ basicType-> get_kind()];169 } 170 171 void Mangler_old::postvisit( PointerType * pointerType ) {167 assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind ); 168 mangleName << Encoding::basicTypes[ basicType->kind ]; 169 } 170 171 void Mangler_old::postvisit( const PointerType * pointerType ) { 172 172 printQualifiers( pointerType ); 173 173 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers … … 176 176 } 177 177 178 void Mangler_old::postvisit( ArrayType * arrayType ) {178 void Mangler_old::postvisit( const ArrayType * arrayType ) { 179 179 // TODO: encode dimension 180 180 printQualifiers( arrayType ); … … 183 183 } 184 184 185 void Mangler_old::postvisit( ReferenceType * refType ) {185 void Mangler_old::postvisit( const ReferenceType * refType ) { 186 186 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload. 187 187 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.), … … 202 202 } 203 203 204 void Mangler_old::postvisit( FunctionType * functionType ) {204 void Mangler_old::postvisit( const FunctionType * functionType ) { 205 205 printQualifiers( functionType ); 206 206 mangleName << Encoding::function; … … 219 219 } 220 220 221 void Mangler_old::mangleRef( ReferenceToType * refType, std::string prefix ) {221 void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) { 222 222 printQualifiers( refType ); 223 223 … … 225 225 226 226 if ( mangleGenericParams ) { 227 std::list< Expression* >& params = refType->parameters;227 const std::list< Expression* > & params = refType->parameters; 228 228 if ( ! params.empty() ) { 229 229 mangleName << "_"; 230 for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param) {231 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );232 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString( *param));230 for ( const Expression * param : params ) { 231 const TypeExpr * paramType = dynamic_cast< const TypeExpr * >( param ); 232 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param)); 233 233 maybeAccept( paramType->type, *visitor ); 234 234 } … … 238 238 } 239 239 240 void Mangler_old::postvisit( StructInstType * aggregateUseType ) {240 void Mangler_old::postvisit( const StructInstType * aggregateUseType ) { 241 241 mangleRef( aggregateUseType, Encoding::struct_t ); 242 242 } 243 243 244 void Mangler_old::postvisit( UnionInstType * aggregateUseType ) {244 void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) { 245 245 mangleRef( aggregateUseType, Encoding::union_t ); 246 246 } 247 247 248 void Mangler_old::postvisit( EnumInstType * aggregateUseType ) {248 void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) { 249 249 mangleRef( aggregateUseType, Encoding::enum_t ); 250 250 } 251 251 252 void Mangler_old::postvisit( TypeInstType * typeInst ) {252 void Mangler_old::postvisit( const TypeInstType * typeInst ) { 253 253 VarMapType::iterator varNum = varNums.find( typeInst->get_name() ); 254 254 if ( varNum == varNums.end() ) { … … 266 266 } 267 267 268 void Mangler_old::postvisit( TraitInstType * inst ) {268 void Mangler_old::postvisit( const TraitInstType * inst ) { 269 269 printQualifiers( inst ); 270 270 mangleName << inst->name.size() << inst->name; 271 271 } 272 272 273 void Mangler_old::postvisit( TupleType * tupleType ) {273 void Mangler_old::postvisit( const TupleType * tupleType ) { 274 274 printQualifiers( tupleType ); 275 275 mangleName << Encoding::tuple << tupleType->types.size(); … … 277 277 } 278 278 279 void Mangler_old::postvisit( VarArgsType * varArgsType ) {279 void Mangler_old::postvisit( const VarArgsType * varArgsType ) { 280 280 printQualifiers( varArgsType ); 281 281 static const std::string vargs = "__builtin_va_list"; … … 283 283 } 284 284 285 void Mangler_old::postvisit( ZeroType * ) {285 void Mangler_old::postvisit( const ZeroType * ) { 286 286 mangleName << Encoding::zero; 287 287 } 288 288 289 void Mangler_old::postvisit( OneType * ) {289 void Mangler_old::postvisit( const OneType * ) { 290 290 mangleName << Encoding::one; 291 291 } 292 292 293 void Mangler_old::postvisit( QualifiedType * qualType ) {293 void Mangler_old::postvisit( const QualifiedType * qualType ) { 294 294 bool inqual = inQualifiedType; 295 295 if (! inqual ) { … … 307 307 } 308 308 309 void Mangler_old::postvisit( TypeDecl * decl ) {309 void Mangler_old::postvisit( const TypeDecl * decl ) { 310 310 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be 311 311 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa. … … 314 314 // aside from the assert false. 315 315 assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl)); 316 assertf( decl-> get_kind() < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->get_kind());317 mangleName << Encoding::typeVariables[ decl-> get_kind()] << ( decl->name.length() ) << decl->name;316 assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind ); 317 mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name; 318 318 } 319 319 … … 324 324 } 325 325 326 void Mangler_old::printQualifiers( Type * type ) {326 void Mangler_old::printQualifiers( const Type * type ) { 327 327 // skip if not including qualifiers 328 328 if ( typeMode ) return; 329 if ( ! type-> get_forall().empty() ) {329 if ( ! type->forall.empty() ) { 330 330 std::list< std::string > assertionNames; 331 331 int dcount = 0, fcount = 0, vcount = 0, acount = 0; 332 332 mangleName << Encoding::forall; 333 for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i) {334 switch ( (*i)->get_kind()) {333 for ( const TypeDecl * i : type->forall ) { 334 switch ( i->kind ) { 335 335 case TypeDecl::Dtype: 336 336 dcount++; … … 345 345 assert( false ); 346 346 } // switch 347 varNums[ (*i)->name ] = std::make_pair( nextVarNum, (int)(*i)->get_kind());348 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert) {349 PassVisitor<Mangler_old> sub_mangler( 347 varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind ); 348 for ( const DeclarationWithType * assert : i->assertions ) { 349 PassVisitor<Mangler_old> sub_mangler( 350 350 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 351 (*assert)->accept( sub_mangler );351 assert->accept( sub_mangler ); 352 352 assertionNames.push_back( sub_mangler.pass.get_mangleName() ); 353 353 acount++; … … 436 436 437 437 private: 438 Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 438 Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 439 439 int nextVarNum, const VarMapType& varNums ); 440 440 friend class ast::Pass<Mangler_new>; … … 457 457 namespace { 458 458 Mangler_new::Mangler_new( Mangle::Mode mode ) 459 : nextVarNum( 0 ), isTopLevel( true ), 459 : nextVarNum( 0 ), isTopLevel( true ), 460 460 mangleOverridable ( ! mode.no_overrideable ), 461 typeMode ( mode.type ), 461 typeMode ( mode.type ), 462 462 mangleGenericParams( ! mode.no_generic_params ) {} 463 464 Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 463 464 Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 465 465 int nextVarNum, const VarMapType& varNums ) 466 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 467 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 466 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 467 mangleOverridable( mangleOverridable ), typeMode( typeMode ), 468 468 mangleGenericParams( mangleGenericParams ) {} 469 469 … … 693 693 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind ); 694 694 for ( const ast::DeclWithType * assert : decl->assertions ) { 695 ast::Pass<Mangler_new> sub_mangler( 695 ast::Pass<Mangler_new> sub_mangler( 696 696 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ); 697 697 assert->accept( sub_mangler ); -
src/SymTab/Mangler.h
r8fd52e90 r6f096d2 40 40 namespace Mangler { 41 41 /// Mangle syntax tree object; primary interface to clients 42 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );42 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true ); 43 43 44 44 /// Mangle a type name; secondary interface 45 std::string mangleType( Type* ty );45 std::string mangleType( const Type * ty ); 46 46 /// Mangle ignoring generic type parameters 47 std::string mangleConcrete( Type* ty );47 std::string mangleConcrete( const Type * ty ); 48 48 49 49 namespace Encoding { -
src/SynTree/Visitor.h
r8fd52e90 r6f096d2 222 222 223 223 template< typename TreeType, typename VisitorType > 224 inline void maybeAccept( TreeType * tree, VisitorType &visitor ) {224 inline void maybeAccept( TreeType * tree, VisitorType & visitor ) { 225 225 if ( tree ) { 226 226 tree->accept( visitor ); … … 228 228 } 229 229 230 template< typename TreeType, typename VisitorType > 231 inline void maybeAccept( const TreeType * tree, VisitorType & visitor ) { 232 if ( tree ) { 233 tree->accept( visitor ); 234 } 235 } 236 230 237 template< typename Container, typename VisitorType > 231 inline void acceptAll( Container & container, VisitorType &visitor ) {238 inline void acceptAll( Container & container, VisitorType & visitor ) { 232 239 SemanticErrorException errors; 233 for ( typename Container::iterator i = container.begin(); i != container.end(); ++i) {240 for ( const auto * i : container ) { 234 241 try { 235 if ( *i ) { 236 (*i)->accept( visitor ); 242 if ( i ) { 243 i->accept( visitor ); 244 } 245 } catch( SemanticErrorException & e ) { 246 errors.append( e ); 247 } 248 } 249 if ( ! errors.isEmpty() ) { 250 throw errors; 251 } 252 } 253 254 template< typename Container, typename VisitorType > 255 inline void acceptAll( const Container & container, VisitorType & visitor ) { 256 SemanticErrorException errors; 257 for ( const auto * i : container ) { 258 try { 259 if ( i ) { 260 i->accept( visitor ); 237 261 } 238 262 } catch( SemanticErrorException &e ) {
Note: See TracChangeset
for help on using the changeset viewer.