Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.cc

    r0b5d871 rb8524ca  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Nov 9 13:12:24 2016
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Wed Nov 9 13:20:24 2016
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jun 12 16:40:00 2016
     13// Update Count     : 3
    1414//
    1515
    1616#include "Explode.h"
    17 #include "SynTree/Mutator.h"
    18 #include "Common/PassVisitor.h"
     17#include <list>                  // for list
     18
     19#include "SynTree/Mutator.h"     // for Mutator
     20#include "Common/PassVisitor.h"  // for PassVisitor
    1921
    2022namespace Tuples {
     
    104106                return expr;
    105107        }
     108
     109namespace {
     110
     111// Remove one level of reference from a reference type.
     112const 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
     121struct 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
     179const 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
    106188} // namespace Tuples
    107189
Note: See TracChangeset for help on using the changeset viewer.