Ignore:
Timestamp:
Jun 17, 2019, 3:55:21 PM (3 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
Children:
e6faef4
Parents:
6e55240
Message:

Implemented new versions of Tuples/Explode?.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.cc

    r6e55240 rb910d15  
    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
     
    106106                return expr;
    107107        }
     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->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
     181const 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
    108191} // namespace Tuples
    109192
Note: See TracChangeset for help on using the changeset viewer.