Ignore:
Timestamp:
Nov 17, 2017, 10:56:16 AM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
cdbfab0
Parents:
f5c3b6c (diff), b7f8cb4 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into fix-bug-51

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cc

    rf5c3b6c r0fe4e62  
    2020#include <memory>                          // for unique_ptr, allocator_trai...
    2121#include <string>                          // for string
     22#include <vector>
    2223
    2324#include "CodeGen/OperatorTable.h"
     
    3334#include "ResolvExpr/Resolver.h"           // for resolveCtorInit
    3435#include "ResolvExpr/TypeEnvironment.h"    // for TypeEnvironment
     36#include "ResolvExpr/typeops.h"            // for combos
    3537#include "SynTree/Declaration.h"           // for ObjectDecl
    3638#include "SynTree/Expression.h"            // for Expression, CastExpr, Name...
     
    5254                // dispatcher for Tuple (multiple and mass) assignment operations
    5355                TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
    54                 void spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities );
     56                void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args );
    5557
    5658          private:
     
    5961                struct Matcher {
    6062                  public:
    61                         Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
     63                        Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
     64                                ResolvExpr::AltList& rhs );
    6265                        virtual ~Matcher() {}
    6366                        virtual void match( std::list< Expression * > &out ) = 0;
     
    7275                struct MassAssignMatcher : public Matcher {
    7376                  public:
    74                         MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
     77                        MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
     78                                const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    7579                        virtual void match( std::list< Expression * > &out );
    7680                };
     
    7882                struct MultipleAssignMatcher : public Matcher {
    7983                  public:
    80                         MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts );
     84                        MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
     85                                const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    8186                        virtual void match( std::list< Expression * > &out );
    8287                };
     
    114119        }
    115120
    116         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
     121        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
     122                                std::vector<ResolvExpr::AlternativeFinder> &args ) {
    117123                TupleAssignSpotter spotter( currentFinder );
    118                 spotter.spot( expr, possibilities );
     124                spotter.spot( expr, args );
    119125        }
    120126
     
    122128                : currentFinder(f) {}
    123129
    124         void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
     130        void TupleAssignSpotter::spot( UntypedExpr * expr,
     131                        std::vector<ResolvExpr::AlternativeFinder> &args ) {
    125132                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    126133                        if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
    127                                fname = op->get_name();
    128                                 PRINT( std::cerr << "TupleAssignment: " << fname << std::endl; )
    129                                 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    130                                         if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
    131                                         if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) {
    132                                                 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it
    133                                                 continue;
     134                                fname = op->get_name();
     135
     136                                // AlternativeFinder will naturally handle this case case, if it's legal
     137                                if ( args.size() == 0 ) return;
     138
     139                                // if an assignment only takes 1 argument, that's odd, but maybe someone wrote
     140                                // the function, in which case AlternativeFinder will handle it normally
     141                                if ( args.size() == 1 && CodeGen::isAssignment( fname ) ) return;
     142
     143                                // look over all possible left-hand-sides
     144                                for ( ResolvExpr::Alternative& lhsAlt : args[0] ) {
     145                                        // skip non-tuple LHS
     146                                        if ( ! refToTuple(lhsAlt.expr) ) continue;
     147
     148                                        // explode is aware of casts - ensure every LHS expression is sent into explode
     149                                        // with a reference cast
     150                                        // xxx - this seems to change the alternatives before the normal
     151                                        //  AlternativeFinder flow; maybe this is desired?
     152                                        if ( ! dynamic_cast<CastExpr*>( lhsAlt.expr ) ) {
     153                                                lhsAlt.expr = new CastExpr( lhsAlt.expr,
     154                                                                new ReferenceType( Type::Qualifiers(),
     155                                                                        lhsAlt.expr->get_result()->clone() ) );
    134156                                        }
    135157
    136                                         assert( ! ali->empty() );
    137                                         // grab args 2-N and group into a TupleExpr
    138                                         const ResolvExpr::Alternative & alt1 = ali->front();
    139                                         auto begin = std::next(ali->begin(), 1), end = ali->end();
    140                                         PRINT( std::cerr << "alt1 is " << alt1.expr << std::endl; )
    141                                         if ( refToTuple(alt1.expr) ) {
    142                                                 PRINT( std::cerr << "and is reference to tuple" << std::endl; )
    143                                                 if ( isMultAssign( begin, end ) ) {
    144                                                         PRINT( std::cerr << "possible multiple assignment" << std::endl; )
    145                                                         matcher.reset( new MultipleAssignMatcher( *this, *ali ) );
    146                                                 } else {
    147                                                         // mass assignment
    148                                                         PRINT( std::cerr << "possible mass assignment" << std::endl; )
    149                                                         matcher.reset( new MassAssignMatcher( *this,  *ali ) );
     158                                        // explode the LHS so that each field of a tuple-valued-expr is assigned
     159                                        ResolvExpr::AltList lhs;
     160                                        explode( lhsAlt, currentFinder.get_indexer(), back_inserter(lhs), true );
     161                                        for ( ResolvExpr::Alternative& alt : lhs ) {
     162                                                // each LHS value must be a reference - some come in with a cast expression,
     163                                                // if not just cast to reference here
     164                                                if ( ! dynamic_cast<ReferenceType*>( alt.expr->get_result() ) ) {
     165                                                        alt.expr = new CastExpr( alt.expr,
     166                                                                new ReferenceType( Type::Qualifiers(),
     167                                                                        alt.expr->get_result()->clone() ) );
    150168                                                }
     169                                        }
     170
     171                                        if ( args.size() == 1 ) {
     172                                                // mass default-initialization/destruction
     173                                                ResolvExpr::AltList rhs{};
     174                                                matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
    151175                                                match();
     176                                        } else if ( args.size() > 2 ) {
     177                                                // expand all possible RHS possibilities
     178                                                // TODO build iterative version of this instead of using combos
     179                                                std::vector< ResolvExpr::AltList > rhsAlts;
     180                                                combos( std::next(args.begin(), 1), args.end(),
     181                                                        std::back_inserter( rhsAlts ) );
     182                                                for ( const ResolvExpr::AltList& rhsAlt : rhsAlts ) {
     183                                                        // multiple assignment
     184                                                        ResolvExpr::AltList rhs;
     185                                                        explode( rhsAlt, currentFinder.get_indexer(),
     186                                                                std::back_inserter(rhs), true );
     187                                                        matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
     188                                                        match();
     189                                                }
     190                                        } else {
     191                                                for ( const ResolvExpr::Alternative& rhsAlt : args[1] ) {
     192                                                        ResolvExpr::AltList rhs;
     193                                                        if ( isTuple(rhsAlt.expr) ) {
     194                                                                // multiple assignment
     195                                                                explode( rhsAlt, currentFinder.get_indexer(), 
     196                                                                        std::back_inserter(rhs), true );
     197                                                                matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
     198                                                        } else {
     199                                                                // mass assignment
     200                                                                rhs.push_back( rhsAlt );
     201                                                                matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
     202                                                        }
     203                                                        match();
     204                                                }
    152205                                        }
    153206                                }
     
    169222                ResolvExpr::AltList current;
    170223                // now resolve new assignments
    171                 for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
     224                for ( std::list< Expression * >::iterator i = new_assigns.begin();
     225                                i != new_assigns.end(); ++i ) {
    172226                        PRINT(
    173227                                std::cerr << "== resolving tuple assign ==" << std::endl;
     
    175229                        )
    176230
    177                         ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
     231                        ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(),
     232                                currentFinder.get_environ() };
    178233                        try {
    179234                                finder.findWithAdjustment(*i);
     
    196251                // combine assignment environments into combined expression environment
    197252                simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );
    198                 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, ResolvExpr::sumCost( current  ) + matcher->baseCost ) );
    199         }
    200 
    201         TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter), baseCost( ResolvExpr::sumCost( alts ) ) {
    202                 assert( ! alts.empty() );
    203                 // combine argument environments into combined expression environment
    204                 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
    205 
    206                 ResolvExpr::Alternative lhsAlt = alts.front();
    207                 // explode is aware of casts - ensure every LHS expression is sent into explode with a reference cast
    208                 if ( ! dynamic_cast< CastExpr * >( lhsAlt.expr ) ) {
    209                         lhsAlt.expr = new CastExpr( lhsAlt.expr, new ReferenceType( Type::Qualifiers(), lhsAlt.expr->get_result()->clone() ) );
    210                 }
    211 
    212                 // explode the lhs so that each field of the tuple-valued-expr is assigned.
    213                 explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs), true );
    214 
    215                 for ( ResolvExpr::Alternative & alt : lhs ) {
    216                         // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here.
    217                         if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) {
    218                                 alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) );
    219                         }
    220                 }
    221         }
    222 
    223         TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
    224                 assert( alts.size() == 1 || alts.size() == 2 );
    225                 if ( alts.size() == 2 ) {
    226                         rhs.push_back( alts.back() );
    227                 }
    228         }
    229 
    230         TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
    231                 // explode the rhs so that each field of the tuple-valued-expr is assigned.
    232                 explode( std::next(alts.begin(), 1), alts.end(), spotter.currentFinder.get_indexer(), back_inserter(rhs), true );
     253                currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(
     254                        new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv,
     255                        ResolvExpr::sumCost( current ) + matcher->baseCost ) );
     256        }
     257
     258        TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter,
     259                const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs )
     260        : lhs(lhs), rhs(rhs), spotter(spotter),
     261          baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
     262                simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );
     263                simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv );
    233264        }
    234265
Note: See TracChangeset for help on using the changeset viewer.