Changeset c6b4432 for src/Tuples/Explode.cc
- Timestamp:
- Nov 8, 2023, 2:01:11 PM (8 months ago)
- Branches:
- master
- Children:
- 3e4bf0d, f5ec35a
- Parents:
- 790d835
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/Explode.cc
r790d835 rc6b4432 15 15 16 16 #include "Explode.h" 17 #include <list> // for list18 17 19 18 #include "AST/Pass.hpp" // for Pass 20 #include "SynTree/Mutator.h" // for Mutator21 #include "Common/PassVisitor.h" // for PassVisitor22 19 23 20 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 exprs45 exprs.push_back( applyCast( expr, false ) );46 }47 // want the top-level expression to be cast to reference type, but not nested48 // tuple expressions49 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 type59 return expr->clone();60 } else {61 // anything else should be cast to reference as normal62 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 than69 // type T. In particular, this transformation helps with generating the70 // correct code for reference-cast member tuple expressions, since the result71 // 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 reference77 // than it had coming into this function. To ensure types still match correctly, need to cast78 // 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 the89 // field is consistent with the type of the tuple expr, since the field90 // 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 } // namespace99 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 appropriate105 expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );106 }107 return expr;108 }109 21 110 22 namespace {
Note: See TracChangeset
for help on using the changeset viewer.