Changes in src/Tuples/Explode.cc [c6b4432:bccd70a]
- File:
-
- 1 edited
-
src/Tuples/Explode.cc (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/Explode.cc
rc6b4432 rbccd70a 15 15 16 16 #include "Explode.h" 17 #include <list> // for list 17 18 18 19 #include "AST/Pass.hpp" // for Pass 20 #include "SynTree/Mutator.h" // for Mutator 21 #include "Common/PassVisitor.h" // for PassVisitor 19 22 20 23 namespace Tuples { 24 namespace { 25 // remove one level of reference from a reference type -- may be useful elsewhere. 26 Type * getReferenceBase( Type * t ) { 27 if ( ReferenceType * refType = dynamic_cast<ReferenceType *>( t ) ) { 28 return refType->get_base(); 29 } else { 30 // for the moment, I want to know immediately if a non-reference type is ever passed in here. 31 assertf( false, "getReferenceBase for non-ref: %s", toString( refType ).c_str() ); 32 return nullptr; 33 } 34 } 35 36 struct CastExploder { 37 bool castAdded = false; 38 bool foundUniqueExpr = false; 39 Expression * applyCast( Expression * expr, bool first = true ) { 40 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){ 41 foundUniqueExpr = true; 42 std::list< Expression * > exprs; 43 for ( Expression *& expr : tupleExpr->get_exprs() ) { 44 // move cast into tuple exprs 45 exprs.push_back( applyCast( expr, false ) ); 46 } 47 // want the top-level expression to be cast to reference type, but not nested 48 // tuple expressions 49 if ( first ) { 50 castAdded = true; 51 Expression * tupleExpr = new TupleExpr( exprs ); 52 return new CastExpr( tupleExpr, new ReferenceType( Type::Qualifiers(), tupleExpr->result->clone() ) ); 53 } else { 54 return new TupleExpr( exprs ); 55 } 56 } 57 if ( dynamic_cast<ReferenceType*>( expr->result ) ) { 58 // don't need to cast reference type to another reference type 59 return expr->clone(); 60 } else { 61 // anything else should be cast to reference as normal 62 castAdded = true; 63 return new CastExpr( expr->clone(), new ReferenceType( Type::Qualifiers(), expr->result->clone() ) ); 64 } 65 } 66 67 Expression * postmutate( UniqueExpr * uniqueExpr ) { 68 // move cast into unique expr so that the unique expr has type T& rather than 69 // type T. In particular, this transformation helps with generating the 70 // correct code for reference-cast member tuple expressions, since the result 71 // should now be a tuple of references rather than a reference to a tuple. 72 // Still, this code is a bit awkward, and could use some improvement. 73 UniqueExpr * newUniqueExpr = new UniqueExpr( applyCast( uniqueExpr->get_expr() ), uniqueExpr->get_id() ); 74 delete uniqueExpr; 75 if ( castAdded ) { 76 // if a cast was added by applyCast, then unique expr now has one more layer of reference 77 // than it had coming into this function. To ensure types still match correctly, need to cast 78 // to reference base so that outer expressions are still correct. 79 castAdded = false; 80 Type * toType = getReferenceBase( newUniqueExpr->result ); 81 return new CastExpr( newUniqueExpr, toType->clone() ); 82 } 83 return newUniqueExpr; 84 } 85 86 87 Expression * postmutate( TupleIndexExpr * tupleExpr ) { 88 // tuple index expr needs to be rebuilt to ensure that the type of the 89 // field is consistent with the type of the tuple expr, since the field 90 // may have changed from type T to T&. 91 Expression * expr = tupleExpr->get_tuple(); 92 tupleExpr->set_tuple( nullptr ); 93 TupleIndexExpr * ret = new TupleIndexExpr( expr, tupleExpr->get_index() ); 94 delete tupleExpr; 95 return ret; 96 } 97 }; 98 } // namespace 99 100 Expression * distributeReference( Expression * expr ) { 101 PassVisitor<CastExploder> exploder; 102 expr = expr->acceptMutator( exploder ); 103 if ( ! exploder.pass.foundUniqueExpr ) { 104 // if a UniqueExpr was found, then the cast has already been added inside the UniqueExpr as appropriate 105 expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) ); 106 } 107 return expr; 108 } 21 109 22 110 namespace {
Note:
See TracChangeset
for help on using the changeset viewer.