Changeset b910d15 for src/Tuples


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

Implemented new versions of Tuples/Explode?.

Location:
src/Tuples
Files:
1 added
4 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
  • src/Tuples/Explode.h

    r6e55240 rb910d15  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Nov 9 13:12:24 2016
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:55:16 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Jun 17 14:36:00 2019
     13// Update Count     : 4
    1414//
    1515
     
    138138        }
    139139
     140const ast::Expr * distributeReference( const ast::Expr * );
     141
     142/// Append candidate to an OutputIterator of Candidates.
     143template<typename OutputIterator>
     144void append( OutputIterator out, const ast::Expr * expr, const ast::TypeEnvironment & env,
     145                const ast::OpenVarSet & open, const ast::AssertionList & need,
     146                const ResolvExpr::Cost & cost, const ResolvExpr::Cost & cvtCost ) {
     147        ast::TypeEnvironment copyEnv = env;
     148        ast::OpenVarSet copyOpen = open;
     149        ast::AssertionSet set;
     150        mergeAssertionSet( set, need );
     151        *out++ = std::make_shared<ResolvExpr::Candidate>( expr, std::move( copyEnv ),
     152                std::move( copyOpen ), std::move( set ), cost, cvtCost );
     153}
     154
     155/// Append candidate to an ExplodedArg.
     156static inline void append( ResolvExpr::ExplodedArg& ea, const ast::Expr * expr,
     157                const ast::TypeEnvironment&, const ast::OpenVarSet&,
     158                const ast::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
     159        // I'm not sure why most of the arguments are unused. But they were in the old version.
     160        ea.exprs.emplace_back( expr );
     161}
     162
     163/// Check if the expression is a cast to a reference type, return it if it is.
     164static inline const ast::CastExpr * isReferenceCast( const ast::Expr * expr ) {
     165        if ( const ast::CastExpr * cast = dynamic_cast< const ast::CastExpr * >( expr ) ) {
     166                if ( dynamic_cast< const ast::ReferenceType * >( cast->result.get() ) ) {
     167                        return cast;
     168                }
     169        }
     170        return nullptr;
     171}
     172
     173/// helper function (indirectely) used by explode
     174template< typename Output >
     175void explodeRecursive(
     176        const ast::CastExpr * expr, const ResolvExpr::Candidate & arg,
     177        const ast::SymbolTable & symtab, Output && out
     178) {
     179}
     180
    140181/// helper function used by explode
    141182template< typename Output >
    142 void explodeUnique( 
    143         const ast::Expr * expr, const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab,
    144         Output && out, bool isTupleAssign
     183void explodeUnique(
     184        const ast::ptr< ast::Expr > & expr, const ResolvExpr::Candidate & arg,
     185        const ast::SymbolTable & symtab, Output && out, bool isTupleAssign
    145186) {
    146         #warning unimplemented
    147         (void)expr; (void)arg; (void)symtab; (void)out; (void)isTupleAssign;
    148         assert(false);
     187        // Tuple assignment can use a faster method if it is cast. Uses recursive exploding.
     188        if ( isTupleAssign ) if ( const ast::CastExpr * castExpr = isReferenceCast( expr ) ) {
     189                ResolvExpr::CandidateList candidates;
     190                explodeUnique( castExpr->arg, arg, symtab, back_inserter( candidates ), true );
     191                for ( ResolvExpr::CandidateRef & cand : candidates ) {
     192                        // Distribute the reference cast over all components of the candidate.
     193                        append( std::forward<Output>(out), distributeReference( cand->expr ), cand->env,
     194                                cand->open, cand->need, cand->cost, cand->cvtCost );
     195                }
     196                return;
     197        }
     198        const ast::Type * res = expr->result->stripReferences();
     199        if ( const ast::TupleType * tupleType = dynamic_cast< const ast::TupleType * >( res ) ) {
     200                if ( const ast::ptr< ast::TupleExpr > & tupleExpr = expr.as< ast::TupleExpr >() ) {
     201                        // Open the tuple expr and continue on its components.
     202                        for ( const ast::Expr * expr : tupleExpr->exprs ) {
     203                                explodeUnique( expr, arg, symtab, std::forward<Output>(out), isTupleAssign );
     204                        }
     205                } else {
     206                        ast::ptr< ast::Expr > local = expr;
     207                        // Expressions which may have side effects require a single unique instance.
     208                        if ( Tuples::maybeImpureIgnoreUnique( local ) ) {
     209                                local = new ast::UniqueExpr( local->location, local );
     210                        }
     211                        // Cast a reference away to a value-type to allow further explosion.
     212                        if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) {
     213                                local = new ast::CastExpr( local->location, local, tupleType );
     214                        }
     215                        // Now we have to go across the tuple via indexing.
     216                        for ( unsigned int i = 0 ; i < tupleType->size() ; ++i ) {
     217                                ast::TupleIndexExpr * idx = new ast::TupleIndexExpr( local->location, local, i );
     218                                explodeUnique( idx, arg, symtab, std::forward<Output>(out), isTupleAssign );
     219                                // TODO: We need more input to figure out the exact lifetimes of these types.
     220                                // delete idx;
     221                        }
     222                        // delete local;
     223                }
     224        } else {
     225                // For atomic/non-tuple types, no explosion is used.
     226                append( std::forward<Output>(out), expr, arg.env, arg.open, arg.need, arg.cost,
     227                        arg.cvtCost );
     228        }
    149229}
    150230
    151231/// expands a tuple-valued candidate into multiple candidates, each with a non-tuple type
    152232template< typename Output >
    153 void explode( 
    154         const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out, 
     233void explode(
     234        const ResolvExpr::Candidate & arg, const ast::SymbolTable & symtab, Output && out,
    155235        bool isTupleAssign = false
    156236) {
  • src/Tuples/Tuples.h

    r6e55240 rb910d15  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:55:00 2017
    13 // Update Count     : 16
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jun 12 10:39:00 2017
     13// Update Count     : 17
    1414//
    1515
     
    5757        bool maybeImpure( Expression * expr );
    5858
    59         /// returns true if the expression may contain side-effect, ignoring the presence of unique expressions.
     59        /// Returns true if the expression may contain side-effect,
     60        /// ignoring the presence of unique expressions.
    6061        bool maybeImpureIgnoreUnique( Expression * expr );
     62        bool maybeImpureIgnoreUnique( const ast::Expr * expr );
    6163} // namespace Tuples
    6264
  • src/Tuples/module.mk

    r6e55240 rb910d15  
    1515###############################################################################
    1616
    17 SRC += Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc Tuples/Explode.cc
    18 SRCDEMANGLE += Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc Tuples/Explode.cc
     17SRC += Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc Tuples/Explode.cc \
     18        Tuples/Tuples.cc
     19SRCDEMANGLE += Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc Tuples/Explode.cc \
     20        Tuples/Tuples.cc
Note: See TracChangeset for help on using the changeset viewer.