Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.cc

    rc6b4432 rbccd70a  
    1515
    1616#include "Explode.h"
     17#include <list>                  // for list
    1718
    1819#include "AST/Pass.hpp"          // for Pass
     20#include "SynTree/Mutator.h"     // for Mutator
     21#include "Common/PassVisitor.h"  // for PassVisitor
    1922
    2023namespace 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 exprs
     45                                                exprs.push_back( applyCast( expr, false ) );
     46                                        }
     47                                        // want the top-level expression to be cast to reference type, but not nested
     48                                        // tuple expressions
     49                                        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 type
     59                                        return expr->clone();
     60                                } else {
     61                                        // anything else should be cast to reference as normal
     62                                        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 than
     69                                // type T. In particular, this transformation helps with generating the
     70                                // correct code for reference-cast member tuple expressions, since the result
     71                                // 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 reference
     77                                        // than it had coming into this function. To ensure types still match correctly, need to cast
     78                                        //  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 the
     89                                // field is consistent with the type of the tuple expr, since the field
     90                                // 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        } // namespace
     99
     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 appropriate
     105                        expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
     106                }
     107                return expr;
     108        }
    21109
    22110namespace {
Note: See TracChangeset for help on using the changeset viewer.