Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.cc

    rb8524ca r0b5d871  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Nov 9 13:12:24 2016
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jun 12 16:40:00 2016
    13 // Update Count     : 3
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Nov 9 13:20:24 2016
     13// Update Count     : 2
    1414//
    1515
    1616#include "Explode.h"
    17 #include <list>                  // for list
    18 
    19 #include "SynTree/Mutator.h"     // for Mutator
    20 #include "Common/PassVisitor.h"  // for PassVisitor
     17#include "SynTree/Mutator.h"
     18#include "Common/PassVisitor.h"
    2119
    2220namespace Tuples {
     
    106104                return expr;
    107105        }
    108 
    109 namespace {
    110 
    111 // Remove one level of reference from a reference type.
    112 const ast::Type * getReferenceBase( const ast::Type * t ) {
    113         if ( const ast::ReferenceType * ref = dynamic_cast< const ast::ReferenceType * >( t ) ) {
    114                 return ref->base;
    115         } else {
    116                 assertf( false, "getReferenceBase for non-ref: %s", toString( t ).c_str() );
    117                 return nullptr;
    118         }
    119 }
    120 
    121 struct CastExploderCore {
    122         bool castAdded = false;
    123         bool foundUniqueExpr = false;
    124         const ast::Expr * applyCast( const ast::Expr * expr, bool first = true ) {
    125                 // On tuple push the cast down.
    126                 if ( const ast::TupleExpr * tupleExpr = dynamic_cast< const ast::TupleExpr * >( expr ) ) {
    127                         foundUniqueExpr = true;
    128                         std::vector< ast::ptr< ast::Expr > > exprs;
    129                         for ( const ast::Expr * expr : tupleExpr->exprs ) {
    130                                 exprs.emplace_back( applyCast( expr, false ) );
    131                                 //exprs.emplace_back( ast::ptr< ast::Expr >( applyCast( expr, false ) ) );
    132                         }
    133                         if ( first ) {
    134                                 castAdded = true;
    135                                 const ast::Expr * tuple = new ast::TupleExpr{
    136                                         tupleExpr->location, std::move( exprs ) };
    137                                 return new ast::CastExpr{ tuple, new ast::ReferenceType{ tuple->result } };
    138                         } else {
    139                                 return new ast::TupleExpr( tupleExpr->location, std::move( exprs ) );
    140                         }
    141                 }
    142                 if ( dynamic_cast< const ast::ReferenceType * >( expr->result.get() ) ) {
    143                         return expr;
    144                 } else {
    145                         castAdded = true;
    146                         return new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
    147                 }
    148         }
    149 
    150         const ast::Expr * postmutate( const ast::UniqueExpr * node ) {
    151                 // move cast into unique expr so that the unique expr has type T& rather than
    152                 // type T. In particular, this transformation helps with generating the
    153                 // correct code for reference-cast member tuple expressions, since the result
    154                 // should now be a tuple of references rather than a reference to a tuple.
    155                 // Still, this code is a bit awkward, and could use some improvement.
    156                 const ast::UniqueExpr * newNode = new ast::UniqueExpr( node->location,
    157                                 applyCast( node->expr ), node->id );
    158                 if ( castAdded ) {
    159                         // if a cast was added by applyCast, then unique expr now has one more layer of reference
    160                         // than it had coming into this function. To ensure types still match correctly, need to cast
    161                         //  to reference base so that outer expressions are still correct.
    162                         castAdded = false;
    163                         const ast::Type * newType = getReferenceBase( newNode->result );
    164                         return new ast::CastExpr{ newNode->location, node, newType };
    165                 }
    166                 return newNode;
    167         }
    168 
    169         const ast::Expr * postmutate( const ast::TupleIndexExpr * tupleExpr ) {
    170                 // tuple index expr needs to be rebuilt to ensure that the type of the
    171                 // field is consistent with the type of the tuple expr, since the field
    172                 // may have changed from type T to T&.
    173                 return new ast::TupleIndexExpr( tupleExpr->location, tupleExpr->tuple, tupleExpr->index );
    174         }
    175 };
    176 
    177 } // namespace
    178 
    179 const ast::Expr * distributeReference( const ast::Expr * expr ) {
    180         ast::Pass<CastExploderCore> exploder;
    181         expr = expr->accept( exploder );
    182         if ( ! exploder.pass.foundUniqueExpr ) {
    183                 expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
    184         }
    185         return expr;
    186 }
    187 
    188106} // namespace Tuples
    189107
Note: See TracChangeset for help on using the changeset viewer.