Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.cc

    rb910d15 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->location,
    138                                         tuple, new ast::ReferenceType( tuple->result.get(), ast::CV::Qualifiers() ) );
    139                         } else {
    140                                 return new ast::TupleExpr( tupleExpr->location, std::move( exprs ) );
    141                         }
    142                 }
    143                 if ( dynamic_cast< const ast::ReferenceType * >( expr->result.get() ) ) {
    144                         return expr;
    145                 } else {
    146                         castAdded = true;
    147                         return new ast::CastExpr( expr->location, expr,
    148                                 new ast::ReferenceType( expr->result, ast::CV::Qualifiers() ) );
    149                 }
    150         }
    151 
    152         const ast::Expr * postmutate( const ast::UniqueExpr * node ) {
    153                 // move cast into unique expr so that the unique expr has type T& rather than
    154                 // type T. In particular, this transformation helps with generating the
    155                 // correct code for reference-cast member tuple expressions, since the result
    156                 // should now be a tuple of references rather than a reference to a tuple.
    157                 // Still, this code is a bit awkward, and could use some improvement.
    158                 const ast::UniqueExpr * newNode = new ast::UniqueExpr( node->location,
    159                                 applyCast( node->expr ), node->id );
    160                 if ( castAdded ) {
    161                         // if a cast was added by applyCast, then unique expr now has one more layer of reference
    162                         // than it had coming into this function. To ensure types still match correctly, need to cast
    163                         //  to reference base so that outer expressions are still correct.
    164                         castAdded = false;
    165                         const ast::Type * newType = getReferenceBase( newNode->result );
    166                         return new ast::CastExpr( newNode->location, node, newType );
    167                 }
    168                 return newNode;
    169         }
    170 
    171         const ast::Expr * postmutate( const ast::TupleIndexExpr * tupleExpr ) {
    172                 // tuple index expr needs to be rebuilt to ensure that the type of the
    173                 // field is consistent with the type of the tuple expr, since the field
    174                 // may have changed from type T to T&.
    175                 return new ast::TupleIndexExpr( tupleExpr->location, tupleExpr->tuple, tupleExpr->index );
    176         }
    177 };
    178 
    179 } // namespace
    180 
    181 const ast::Expr * distributeReference( const ast::Expr * expr ) {
    182         ast::Pass<CastExploderCore> exploder;
    183         expr = expr->accept( exploder );
    184         if ( ! exploder.pass.foundUniqueExpr ) {
    185                 expr = new ast::CastExpr( expr->location, expr,
    186                         new ast::ReferenceType( expr->result, ast::CV::Qualifiers() ) );
    187         }
    188         return expr;
    189 }
    190 
    191106} // namespace Tuples
    192107
Note: See TracChangeset for help on using the changeset viewer.