Changeset 7831527


Ignore:
Timestamp:
Nov 8, 2017, 4:34:54 PM (4 years ago)
Author:
Aaron Moss <a3moss@…>
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:
3f7e12c
Parents:
fae6f21
Message:

Switch in new TupleAssignment?

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cc

    rfae6f21 r7831527  
    2020#include <memory>                          // for unique_ptr, allocator_trai...
    2121#include <string>                          // for string
     22#include <vector>
    2223
    2324#include "CodeGen/OperatorTable.h"
     
    6061                struct Matcher {
    6162                  public:
    62                         Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
     63                        Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
     64                                ResolvExpr::AltList& rhs );
    6365                        virtual ~Matcher() {}
    6466                        virtual void match( std::list< Expression * > &out ) = 0;
     
    7375                struct MassAssignMatcher : public Matcher {
    7476                  public:
    75                         MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
     77                        MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
     78                                const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    7679                        virtual void match( std::list< Expression * > &out );
    7780                };
     
    7982                struct MultipleAssignMatcher : public Matcher {
    8083                  public:
    81                         MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts );
     84                        MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
     85                                const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    8286                        virtual void match( std::list< Expression * > &out );
    8387                };
     
    9195        bool isTuple( Expression *expr ) {
    9296                if ( ! expr ) return false;
    93                 assert( expr->result );
     97                assert( expr->has_result() );
    9498                return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
    9599        }
     
    116120
    117121        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
    118                 std::vector<ResolvExpr::AlternativeFinder> &args ) {
    119         TupleAssignSpotter spotter( currentFinder );
    120         spotter.spot( expr, args );
     122                                std::vector<ResolvExpr::AlternativeFinder> &args ) {
     123                TupleAssignSpotter spotter( currentFinder );
     124                spotter.spot( expr, args );
    121125        }
    122126
     
    124128                : currentFinder(f) {}
    125129
    126         void TupleAssignSpotter::spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args ) {
    127                 std::list<ResolvExpr::AltList> possibilities;
    128                 combos( args.begin(), args.end(), back_inserter( possibilities ) );
    129 
     130        void TupleAssignSpotter::spot( UntypedExpr * expr,
     131                        std::vector<ResolvExpr::AlternativeFinder> &args ) {
    130132                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    131133                        if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
    132                                fname = op->get_name();
    133                                 PRINT( std::cerr << "TupleAssignment: " << fname << std::endl; )
    134                                 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    135                                         if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
    136                                         if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) {
    137                                                 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it
    138                                                 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() ) );
    139156                                        }
    140157
    141                                         assert( ! ali->empty() );
    142                                         // grab args 2-N and group into a TupleExpr
    143                                         const ResolvExpr::Alternative & alt1 = ali->front();
    144                                         auto begin = std::next(ali->begin(), 1), end = ali->end();
    145                                         PRINT( std::cerr << "alt1 is " << alt1.expr << std::endl; )
    146                                         if ( refToTuple(alt1.expr) ) {
    147                                                 PRINT( std::cerr << "and is reference to tuple" << std::endl; )
    148                                                 if ( isMultAssign( begin, end ) ) {
    149                                                         PRINT( std::cerr << "possible multiple assignment" << std::endl; )
    150                                                         matcher.reset( new MultipleAssignMatcher( *this, *ali ) );
    151                                                 } else {
    152                                                         // mass assignment
    153                                                         PRINT( std::cerr << "possible mass assignment" << std::endl; )
    154                                                         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() ) );
    155168                                                }
     169                                        }
     170
     171                                        if ( args.size() == 1 ) {
     172                                                // mass default-initialization/destruction
     173                                                ResolvExpr::AltList rhs{};
     174                                                matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
    156175                                                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                                                }
    157205                                        }
    158206                                }
     
    174222                ResolvExpr::AltList current;
    175223                // now resolve new assignments
    176                 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 ) {
    177226                        PRINT(
    178227                                std::cerr << "== resolving tuple assign ==" << std::endl;
     
    180229                        )
    181230
    182                         ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
     231                        ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(),
     232                                currentFinder.get_environ() };
    183233                        try {
    184234                                finder.findWithAdjustment(*i);
     
    201251                // combine assignment environments into combined expression environment
    202252                simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );
    203                 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, ResolvExpr::sumCost( current  ) + matcher->baseCost ) );
    204         }
    205 
    206         TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter), baseCost( ResolvExpr::sumCost( alts ) ) {
    207                 assert( ! alts.empty() );
    208                 // combine argument environments into combined expression environment
    209                 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
    210 
    211                 ResolvExpr::Alternative lhsAlt = alts.front();
    212                 // explode is aware of casts - ensure every LHS expression is sent into explode with a reference cast
    213                 if ( ! dynamic_cast< CastExpr * >( lhsAlt.expr ) ) {
    214                         lhsAlt.expr = new CastExpr( lhsAlt.expr, new ReferenceType( Type::Qualifiers(), lhsAlt.expr->get_result()->clone() ) );
    215                 }
    216 
    217                 // explode the lhs so that each field of the tuple-valued-expr is assigned.
    218                 explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs), true );
    219 
    220                 for ( ResolvExpr::Alternative & alt : lhs ) {
    221                         // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here.
    222                         if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) {
    223                                 alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) );
    224                         }
    225                 }
    226         }
    227 
    228         TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
    229                 assert( alts.size() == 1 || alts.size() == 2 );
    230                 if ( alts.size() == 2 ) {
    231                         rhs.push_back( alts.back() );
    232                 }
    233         }
    234 
    235         TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
    236                 // explode the rhs so that each field of the tuple-valued-expr is assigned.
    237                 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 );
    238264        }
    239265
     
    259285
    260286        ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) {
    261                 assert( expr->result && ! expr->get_result()->isVoid() );
     287                assert( expr->has_result() && ! expr->get_result()->isVoid() );
    262288                ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
    263289                // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
     
    269295                        ctorInit->accept( rm );
    270296                }
    271                 PRINT( std::cerr << "new object: " << ret << std::endl; )
    272297                return ret;
    273298        }
Note: See TracChangeset for help on using the changeset viewer.