Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cc

    rbd4f2e9 rf5854507  
    2020#include <memory>                          // for unique_ptr, allocator_trai...
    2121#include <string>                          // for string
    22 #include <vector>
    2322
    2423#include "CodeGen/OperatorTable.h"
     
    3433#include "ResolvExpr/Resolver.h"           // for resolveCtorInit
    3534#include "ResolvExpr/TypeEnvironment.h"    // for TypeEnvironment
    36 #include "ResolvExpr/typeops.h"            // for combos
    3735#include "SynTree/Declaration.h"           // for ObjectDecl
    3836#include "SynTree/Expression.h"            // for Expression, CastExpr, Name...
     
    5452                // dispatcher for Tuple (multiple and mass) assignment operations
    5553                TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
    56                 void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args );
     54                void spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities );
    5755
    5856          private:
     
    6159                struct Matcher {
    6260                  public:
    63                         Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
    64                                 ResolvExpr::AltList& rhs );
     61                        Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
    6562                        virtual ~Matcher() {}
    6663                        virtual void match( std::list< Expression * > &out ) = 0;
     
    7572                struct MassAssignMatcher : public Matcher {
    7673                  public:
    77                         MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
    78                                 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
     74                        MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
    7975                        virtual void match( std::list< Expression * > &out );
    8076                };
     
    8278                struct MultipleAssignMatcher : public Matcher {
    8379                  public:
    84                         MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
    85                                 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
     80                        MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts );
    8681                        virtual void match( std::list< Expression * > &out );
    8782                };
     
    119114        }
    120115
    121         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
    122                                 std::vector<ResolvExpr::AlternativeFinder> &args ) {
     116        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
    123117                TupleAssignSpotter spotter( currentFinder );
    124                 spotter.spot( expr, args );
     118                spotter.spot( expr, possibilities );
    125119        }
    126120
     
    128122                : currentFinder(f) {}
    129123
    130         void TupleAssignSpotter::spot( UntypedExpr * expr,
    131                         std::vector<ResolvExpr::AlternativeFinder> &args ) {
     124        void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
    132125                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    133126                        if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
    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() ) );
     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;
    156134                                        }
    157135
    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() ) );
     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 ) );
    168150                                                }
    169                                         }
    170 
    171                                         if ( args.size() == 1 ) {
    172                                                 // mass default-initialization/destruction
    173                                                 ResolvExpr::AltList rhs{};
    174                                                 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
    175151                                                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                                                 }
    205152                                        }
    206153                                }
     
    222169                ResolvExpr::AltList current;
    223170                // now resolve new assignments
    224                 for ( std::list< Expression * >::iterator i = new_assigns.begin();
    225                                 i != new_assigns.end(); ++i ) {
     171                for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
    226172                        PRINT(
    227173                                std::cerr << "== resolving tuple assign ==" << std::endl;
     
    229175                        )
    230176
    231                         ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(),
    232                                 currentFinder.get_environ() };
     177                        ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
    233178                        try {
    234179                                finder.findWithAdjustment(*i);
     
    251196                // combine assignment environments into combined expression environment
    252197                simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );
    253                 // xxx -- was push_front
    254                 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative(
    255                         new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv,
    256                         ResolvExpr::sumCost( current ) + matcher->baseCost ) );
    257         }
    258 
    259         TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter,
    260                 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs )
    261         : lhs(lhs), rhs(rhs), spotter(spotter),
    262           baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
    263                 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );
    264                 simpleCombineEnvironments( rhs.begin(), rhs.end(), 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 );
    265233        }
    266234
Note: See TracChangeset for help on using the changeset viewer.