Ignore:
Timestamp:
Nov 29, 2016, 3:30:59 PM (9 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
8e5724e
Parents:
3a2128f (diff), 9129a84 (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' of plg2:software/cfa/cfa-cc

Conflicts:

src/Parser/parser.cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cc

    r3a2128f r1f44196  
    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 : Mon May 18 15:02:53 2015
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Nov 9 13:48:42 2016
    1313// Update Count     : 2
    1414//
     
    1818#include "ResolvExpr/typeops.h"
    1919#include "SynTree/Expression.h"
    20 #include "TupleAssignment.h"
     20#include "SynTree/Initializer.h"
     21#include "Tuples.h"
     22#include "Explode.h"
    2123#include "Common/SemanticError.h"
     24#include "InitTweak/InitTweak.h"
    2225
    2326#include <functional>
     
    2730#include <cassert>
    2831#include <set>
     32#include <unordered_set>
    2933
    3034namespace Tuples {
    31         TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder *f )
    32                 : currentFinder(f), matcher(0), hasMatched( false ) {}
    33 
    34         bool TupleAssignSpotter::pointsToTuple( Expression *expr ) {
     35        class TupleAssignSpotter {
     36          public:
     37                // dispatcher for Tuple (multiple and mass) assignment operations
     38                TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
     39                void spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities );
     40
     41          private:
     42                void match();
     43
     44                struct Matcher {
     45                  public:
     46                        Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
     47                        virtual ~Matcher() {}
     48                        virtual void match( std::list< Expression * > &out ) = 0;
     49                        ResolvExpr::AltList lhs, rhs;
     50                        TupleAssignSpotter &spotter;
     51                        std::list< ObjectDecl * > tmpDecls;
     52                };
     53
     54                struct MassAssignMatcher : public Matcher {
     55                  public:
     56                        MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts );
     57                        virtual void match( std::list< Expression * > &out );
     58                };
     59
     60                struct MultipleAssignMatcher : public Matcher {
     61                  public:
     62                        MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts );
     63                        virtual void match( std::list< Expression * > &out );
     64                };
     65
     66                ResolvExpr::AlternativeFinder &currentFinder;
     67                std::string fname;
     68                std::unique_ptr< Matcher > matcher;
     69        };
     70
     71        /// true if expr is an expression of tuple type, i.e. a tuple expression, tuple variable, or MRV (multiple-return-value) function
     72        bool isTuple( Expression *expr ) {
     73                if ( ! expr ) return false;
     74                assert( expr->has_result() );
     75                return dynamic_cast<TupleExpr *>(expr) || expr->get_result()->size() > 1;
     76        }
     77
     78        template< typename AltIter >
     79        bool isMultAssign( AltIter begin, AltIter end ) {
     80                // multiple assignment if more than one alternative in the range or if
     81                // the alternative is a tuple
     82                if ( begin == end ) return false;
     83                if ( isTuple( begin->expr ) ) return true;
     84                return ++begin != end;
     85        }
     86
     87        bool pointsToTuple( Expression *expr ) {
    3588                // also check for function returning tuple of reference types
    36                 if (AddressExpr *addr = dynamic_cast<AddressExpr *>(expr) )
    37                         if ( isTuple(addr->get_arg() ) )
    38                                 return true;
     89                if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     90                        return pointsToTuple( castExpr->get_arg() );
     91                } else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) {
     92                        return isTuple( addr->get_arg() );
     93                }
    3994                return false;
    4095        }
    4196
    42         bool TupleAssignSpotter::isTupleVar( DeclarationWithType *decl ) {
    43                 if ( dynamic_cast<TupleType *>(decl->get_type()) )
    44                         return true;
    45                 return false;
    46         }
    47 
    48         bool TupleAssignSpotter::isTuple( Expression *expr, bool isRight ) {
    49                 // true if `expr' is an expression returning a tuple: tuple, tuple variable or MRV function
    50                 if ( ! expr ) return false;
    51 
    52                 if ( dynamic_cast<TupleExpr *>(expr) )
    53                         return true;
    54                 else if ( VariableExpr *var = dynamic_cast<VariableExpr *>(expr) ) {
    55                         if ( isTupleVar(var->get_var()) )
    56                                 return true;
    57                 }
    58 
    59                 return false;
    60         }
    61 
    62         bool TupleAssignSpotter::match() {
    63                 assert ( matcher != 0 );
    64 
    65                 std::list< Expression * > new_assigns;
    66                 if ( ! matcher->match(new_assigns) )
    67                         return false;
    68 
    69                 if ( new_assigns.empty() ) return false;
    70                 /*return */matcher->solve( new_assigns );
    71                 if ( dynamic_cast<TupleAssignSpotter::MultipleAssignMatcher *>( matcher ) ) {
    72                         // now resolve new assignments
    73                         std::list< Expression * > solved_assigns;
    74                         ResolvExpr::AltList solved_alts;
    75                         assert( currentFinder != 0 );
    76 
    77                         ResolvExpr::AltList current;
    78                         for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
    79                                 //try {
    80                                 ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
    81                                 finder.findWithAdjustment(*i);
    82                                 // prune expressions that don't coincide with
    83                                 ResolvExpr::AltList alts = finder.get_alternatives();
    84                                 assert( alts.size() == 1 );
    85                                 assert(alts.front().expr != 0 );
    86                                 current.push_back( finder.get_alternatives().front() );
    87                                 solved_assigns.push_back( alts.front().expr->clone() );
    88                                 //solved_assigns.back()->print(std::cerr);
    89                                 /*} catch( ... ) {
    90                                   continue; // no reasonable alternative found
    91                                   }*/
    92                         }
    93                         options.add_option( current );
    94 
    95                         return true;
    96                 } else { // mass assignment
    97                         //if ( new_assigns.empty() ) return false;
    98                         std::list< Expression * > solved_assigns;
    99                         ResolvExpr::AltList solved_alts;
    100                         assert( currentFinder != 0 );
    101 
    102                         ResolvExpr::AltList current;
    103                         if ( optMass.empty() ) {
    104                                 for ( std::list< Expression * >::size_type i = 0; i != new_assigns.size(); ++i )
    105                                         optMass.push_back( ResolvExpr::AltList() );
    106                         }
    107                         int cnt = 0;
    108                         for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i, cnt++ ) {
    109 
    110                                 ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
    111                                 finder.findWithAdjustment(*i);
    112                                 ResolvExpr::AltList alts = finder.get_alternatives();
    113                                 assert( alts.size() == 1 );
    114                                 assert(alts.front().expr != 0 );
    115                                 current.push_back( finder.get_alternatives().front() );
    116                                 optMass[cnt].push_back( finder.get_alternatives().front() );
    117                                 solved_assigns.push_back( alts.front().expr->clone() );
    118                         }
    119 
    120                         return true;
    121                 }
    122 
    123                 return false;
    124         }
    125 
    126         bool TupleAssignSpotter::isMVR( Expression *expr ) {
    127                 if ( expr->get_results().size() > 1 ) {
    128                         // MVR processing
    129                         return true;
    130                 }
    131                 return false;
    132         }
    133 
    134         bool TupleAssignSpotter::isTupleAssignment( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
    135                 if (  NameExpr *assgnop = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    136 
    137                         if ( assgnop->get_name() == std::string("?=?") ) {
    138 
    139                                 for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    140                                         assert( ali->size() == 2 );
    141                                         ResolvExpr::AltList::iterator opit = ali->begin();
    142                                         ResolvExpr::Alternative op1 = *opit, op2 = *(++opit);
    143 
    144                                         if ( pointsToTuple(op1.expr) ) { // also handles tuple vars
    145                                                 if ( isTuple( op2.expr, true ) )
    146                                                         matcher = new MultipleAssignMatcher(op1.expr, op2.expr);
    147                                                 else if ( isMVR( op2.expr ) ) {
    148                                                         // handle MVR differently
    149                                                 } else
     97        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
     98                TupleAssignSpotter spotter( currentFinder );
     99                spotter.spot( expr, possibilities );
     100        }
     101
     102        TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )
     103                : currentFinder(f) {}
     104
     105        void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
     106                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
     107                        if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) {
     108                                fname = op->get_name();
     109                                for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
     110                                        if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
     111                                        if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) {
     112                                                // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it
     113                                                continue;
     114                                        }
     115
     116                                        assert( ! ali->empty() );
     117                                        // grab args 2-N and group into a TupleExpr
     118                                        const ResolvExpr::Alternative & alt1 = ali->front();
     119                                        auto begin = std::next(ali->begin(), 1), end = ali->end();
     120                                        if ( pointsToTuple(alt1.expr) ) {
     121                                                if ( isMultAssign( begin, end ) ) {
     122                                                        matcher.reset( new MultipleAssignMatcher( *this, *ali ) );
     123                                                } else {
    150124                                                        // mass assignment
    151                                                         matcher = new MassAssignMatcher(op1.expr, op2.expr);
    152 
    153                                                 std::list< ResolvExpr::AltList > options;
    154                                                 if ( match() )
    155                                                         /*
    156                                                           if ( hasMatched ) {
    157                                                           // throw SemanticError("Ambiguous tuple assignment");
    158                                                           } else {*/
    159                                                         // Matched for the first time
    160                                                         hasMatched = true;
    161                                                 /*} */
    162                                         } /* else if ( isTuple( op2 ) )
    163                                                  throw SemanticError("Inapplicable tuple assignment.");
    164                                           */
    165                                 }
    166 
    167                                 if ( hasMatched ) {
    168                                         if ( dynamic_cast<TupleAssignSpotter::MultipleAssignMatcher *>( matcher ) ) {
    169                                                 //options.print( std::cerr );
    170                                                 std::list< ResolvExpr::AltList >best = options.get_best();
    171                                                 if ( best.size() == 1 ) {
    172                                                         std::list<Expression *> solved_assigns;
    173                                                         for ( ResolvExpr::AltList::iterator i = best.front().begin(); i != best.front().end(); ++i ) {
    174                                                                 solved_assigns.push_back( i->expr );
    175                                                         }
    176                                                         /* assigning cost zero? */
    177                                                         currentFinder->get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns/*, SolvedTupleExpr::MULTIPLE*/), currentFinder->get_environ(), ResolvExpr::Cost() ) );
     125                                                        matcher.reset( new MassAssignMatcher( *this,  *ali ) );
    178126                                                }
    179                                         } else {
    180                                                 assert( ! optMass.empty() );
    181                                                 ResolvExpr::AltList winners;
    182                                                 for ( std::vector< ResolvExpr::AltList >::iterator i = optMass.begin(); i != optMass.end(); ++i )
    183                                                         findMinCostAlt( i->begin(), i->end(), back_inserter(winners) );
    184 
    185                                                 std::list< Expression *> solved_assigns;
    186                                                 for ( ResolvExpr::AltList::iterator i = winners.begin(); i != winners.end(); ++i )
    187                                                         solved_assigns.push_back( i->expr );
    188                                                 currentFinder->get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns/*, SolvedTupleExpr::MASS*/), currentFinder->get_environ(), ResolvExpr::Cost() ) );
     127                                                match();
    189128                                        }
    190129                                }
    191130                        }
    192131                }
    193                 return hasMatched;
    194         }
    195 
    196         void TupleAssignSpotter::Matcher::init( Expression *_lhs, Expression *_rhs ) {
    197                 lhs.clear();
    198                 if (AddressExpr *addr = dynamic_cast<AddressExpr *>(_lhs) )
    199                         if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(addr->get_arg()) )
    200                                 std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(lhs) );
    201 
    202                 rhs.clear();
    203         }
    204 
    205         TupleAssignSpotter::Matcher::Matcher( /*TupleAssignSpotter &spot,*/ Expression *_lhs, Expression *_rhs ) /*: own_spotter(spot) */{
    206                 init(_lhs,_rhs);
    207         }
    208 
    209         TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( Expression *_lhs, Expression *_rhs )/* : own_spotter(spot) */{
    210                 init(_lhs,_rhs);
    211 
    212                 if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(_rhs) )
    213                         std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(rhs) );
    214         }
    215 
    216         UntypedExpr *TupleAssignSpotter::Matcher::createAssgn( Expression *left, Expression *right ) {
    217                 if ( left && right ) {
    218                         std::list< Expression * > args;
    219                         args.push_back(new AddressExpr(left->clone()));  args.push_back(right->clone());
    220                         return new UntypedExpr(new NameExpr("?=?"), args);
    221                 } else
    222                         throw 0; // xxx - diagnose the problem
    223         }
    224 
    225         bool TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
    226                 if ( lhs.empty() || (rhs.size() != 1) ) return false;
    227 
    228                 for ( std::list< Expression * >::iterator l = lhs.begin(); l != lhs.end(); l++ ) {
    229                         std::list< Expression * > args;
    230                         args.push_back( new AddressExpr(*l) );
    231                         args.push_back( rhs.front() );
    232                         out.push_back( new UntypedExpr(new NameExpr("?=?"), args) );
    233                 }
    234 
    235                 return true;
    236         }
    237 
    238         bool TupleAssignSpotter::MassAssignMatcher::solve( std::list< Expression * > &assigns ) {
    239                 /*
    240                   std::list< Expression * > solved_assigns;
    241                   ResolvExpr::AltList solved_alts;
    242                   assert( currentFinder != 0 );
    243 
    244                   ResolvExpr::AltList current;
    245                   if ( optMass.empty() ) {
    246                   for ( std::list< Expression * >::size_type i = 0; i != new_assigns.size(); ++i )
    247                   optMass.push_back( ResolvExpr::AltList() );
    248                   }
    249                   int cnt = 0;
    250                   for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i, cnt++ ) {
    251 
    252                   ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
    253                   finder.findWithAdjustment(*i);
    254                   ResolvExpr::AltList alts = finder.get_alternatives();
    255                   assert( alts.size() == 1 );
    256                   assert(alts.front().expr != 0 );
    257                   current.push_back( finder.get_alternatives().front() );
    258                   optMass[cnt].push_back( finder.get_alternatives().front() );
    259                   solved_assigns.push_back( alts.front().expr->clone() );
    260                   }
    261                 */
    262                 return true;
    263         }
    264 
    265         bool TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
    266                 // need more complicated matching
     132        }
     133
     134        void TupleAssignSpotter::match() {
     135                assert ( matcher != 0 );
     136
     137                std::list< Expression * > new_assigns;
     138                matcher->match( new_assigns );
     139
     140                if ( new_assigns.empty() ) return;
     141                ResolvExpr::AltList current;
     142                // now resolve new assignments
     143                for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
     144                        ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
     145                        try {
     146                                finder.findWithAdjustment(*i);
     147                        } catch (...) {
     148                                return; // xxx - no match should not mean failure, it just means this particular tuple assignment isn't valid
     149                        }
     150                        // prune expressions that don't coincide with
     151                        ResolvExpr::AltList alts = finder.get_alternatives();
     152                        assert( alts.size() == 1 );
     153                        assert( alts.front().expr != 0 );
     154                        current.push_back( alts.front() );
     155                }
     156
     157                // extract expressions from the assignment alternatives to produce a list of assignments that
     158                // together form a single alternative
     159                std::list< Expression *> solved_assigns;
     160                for ( ResolvExpr::Alternative & alt : current ) {
     161                        solved_assigns.push_back( alt.expr->clone() );
     162                }
     163                // xxx - need to do this??
     164                ResolvExpr::TypeEnvironment compositeEnv;
     165                simpleCombineEnvironments( current.begin(), current.end(), compositeEnv );
     166                currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), compositeEnv, ResolvExpr::sumCost( current ) ) );
     167        }
     168
     169        TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter) {
     170                assert( ! alts.empty() );
     171                ResolvExpr::Alternative lhsAlt = alts.front();
     172                // peel off the cast that exists on ctor/dtor expressions
     173                bool isCast = false;
     174                if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( lhsAlt.expr ) ) {
     175                        lhsAlt.expr = castExpr->get_arg();
     176                        castExpr->set_arg( nullptr );
     177                        delete castExpr;
     178                        isCast = true;
     179                }
     180
     181                // explode the lhs so that each field of the tuple-valued-expr is assigned.
     182                explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs) );
     183
     184                // and finally, re-add the cast to each lhs expr, so that qualified tuple fields can be constructed
     185                if ( isCast ) {
     186                        for ( ResolvExpr::Alternative & alt : lhs ) {
     187                                Expression *& expr = alt.expr;
     188                                Type * castType = expr->get_result()->clone();
     189                                Type * type = InitTweak::getPointerBase( castType );
     190                                assert( type );
     191                                type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
     192                                type->set_isLvalue( true ); // xxx - might not need this
     193                                expr = new CastExpr( expr, castType );
     194                        }
     195                }
     196        }
     197
     198        TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
     199                assert( alts.size() == 1 || alts.size() == 2 );
     200                if ( alts.size() == 2 ) {
     201                        rhs.push_back( alts.back() );
     202                }
     203        }
     204
     205        TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
     206                // explode the rhs so that each field of the tuple-valued-expr is assigned.
     207                explode( std::next(alts.begin(), 1), alts.end(), spotter.currentFinder.get_indexer(), back_inserter(rhs) );
     208        }
     209
     210        UntypedExpr * createFunc( const std::string &fname, ObjectDecl *left, ObjectDecl *right ) {
     211                assert( left );
     212                std::list< Expression * > args;
     213                args.push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( left ) ) ) );
     214                // args.push_back( new AddressExpr( new VariableExpr( left ) ) );
     215                if ( right ) args.push_back( new VariableExpr( right ) );
     216                return new UntypedExpr( new NameExpr( fname ), args );
     217        }
     218
     219        ObjectDecl * newObject( UniqueName & namer, Expression * expr ) {
     220                assert( expr->has_result() && ! expr->get_result()->isVoid() );
     221                return new ObjectDecl( namer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
     222        }
     223
     224        void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
     225                static UniqueName lhsNamer( "__massassign_L" );
     226                static UniqueName rhsNamer( "__massassign_R" );
     227                assert ( ! lhs.empty() && rhs.size() <= 1);
     228
     229                ObjectDecl * rtmp = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr;
     230                for ( ResolvExpr::Alternative & lhsAlt : lhs ) {
     231                        ObjectDecl * ltmp = newObject( lhsNamer, lhsAlt.expr );
     232                        out.push_back( createFunc( spotter.fname, ltmp, rtmp ) );
     233                        tmpDecls.push_back( ltmp );
     234                }
     235                if ( rtmp ) tmpDecls.push_back( rtmp );
     236        }
     237
     238        void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
     239                static UniqueName lhsNamer( "__multassign_L" );
     240                static UniqueName rhsNamer( "__multassign_R" );
     241
     242                // xxx - need more complicated matching?
    267243                if ( lhs.size() == rhs.size() ) {
    268                         zipWith( lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), back_inserter(out), TupleAssignSpotter::Matcher::createAssgn );
    269                         return true;
    270                 } //else
    271                 //std::cerr << "The length of (left, right) is: (" << lhs.size() << "," << rhs.size() << ")" << std::endl;*/
    272                 return false;
    273         }
    274 
    275         bool TupleAssignSpotter::MultipleAssignMatcher::solve( std::list< Expression * > &assigns ) {
    276                 /*
    277                   std::list< Expression * > solved_assigns;
    278                   ResolvExpr::AltList solved_alts;
    279                   assert( currentFinder != 0 );
    280 
    281                   ResolvExpr::AltList current;
    282                   for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
    283                   //try {
    284                   ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
    285                   finder.findWithAdjustment(*i);
    286                   // prune expressions that don't coincide with
    287                   ResolvExpr::AltList alts = finder.get_alternatives();
    288                   assert( alts.size() == 1 );
    289                   assert(alts.front().expr != 0 );
    290                   current.push_back( finder.get_alternatives().front() );
    291                   solved_assigns.push_back( alts.front().expr->clone() );
    292                   //solved_assigns.back()->print(std::cerr);
    293                   //} catch( ... ) {
    294                   //continue; // no reasonable alternative found
    295                   //}
    296                   }
    297                   options.add_option( current );
    298                 */
    299 
    300                 return true;
    301         }
    302 
    303         void TupleAssignSpotter::Options::add_option( ResolvExpr::AltList &opt ) {
    304                 using namespace std;
    305 
    306                 options.push_back( opt );
    307                 /*
    308                   vector< Cost > costs;
    309                   costs.reserve( opt.size() );
    310                   transform( opt.begin(), opt.end(), back_inserter(costs), ptr_fun(extract_cost) );
    311                 */
    312                 // transpose matrix
    313                 if ( costMatrix.empty() )
    314                         for ( unsigned int i = 0; i< opt.size(); ++i)
    315                                 costMatrix.push_back( vector<ResolvExpr::Cost>() );
    316 
    317                 int cnt = 0;
    318                 for ( ResolvExpr::AltList::iterator i = opt.begin(); i != opt.end(); ++i, cnt++ )
    319                         costMatrix[cnt].push_back( i->cost );
    320 
    321                 return;
    322         }
    323 
    324         std::list< ResolvExpr::AltList > TupleAssignSpotter::Options::get_best() {
    325                 using namespace std;
    326                 using namespace ResolvExpr;
    327                 list< ResolvExpr::AltList > ret;
    328                 list< multiset<int> > solns;
    329                 for ( vector< vector<Cost> >::iterator i = costMatrix.begin(); i != costMatrix.end(); ++i ) {
    330                         list<int> current;
    331                         findMinCost( i->begin(), i->end(), back_inserter(current) );
    332                         solns.push_back( multiset<int>(current.begin(), current.end()) );
    333                 }
    334                 // need to combine
    335                 multiset<int> result;
    336                 lift_intersection( solns.begin(), solns.end(), inserter( result, result.begin() ) );
    337                 if ( result.size() != 1 )
    338                         throw SemanticError("Ambiguous tuple expression");
    339                 ret.push_back(get_option( *(result.begin() )));
    340                 return ret;
    341         }
    342 
    343         void TupleAssignSpotter::Options::print( std::ostream &ostr ) {
    344                 using namespace std;
    345 
    346                 for ( vector< vector < ResolvExpr::Cost > >::iterator i = costMatrix.begin(); i != costMatrix.end(); ++i ) {
    347                         for ( vector < ResolvExpr::Cost >::iterator j = i->begin(); j != i->end(); ++j )
    348                                 ostr << *j << " " ;
    349                         ostr << std::endl;
    350                 } // for
    351                 return;
    352         }
    353 
    354         ResolvExpr::Cost extract_cost( ResolvExpr::Alternative &alt ) {
    355                 return alt.cost;
    356         }
    357 
    358         template< typename InputIterator, typename OutputIterator >
    359         void TupleAssignSpotter::Options::findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
    360                 using namespace ResolvExpr;
    361                 std::list<int> alternatives;
    362 
    363                 // select the alternatives that have the minimum parameter cost
    364                 Cost minCost = Cost::infinity;
    365                 unsigned int index = 0;
    366                 for ( InputIterator i = begin; i != end; ++i, index++ ) {
    367                         if ( *i < minCost ) {
    368                                 minCost = *i;
    369                                 alternatives.clear();
    370                                 alternatives.push_back( index );
    371                         } else if ( *i == minCost ) {
    372                                 alternatives.push_back( index );
    373                         }
    374                 }
    375                 std::copy( alternatives.begin(), alternatives.end(), out );
    376         }
    377 
    378         template< class InputIterator, class OutputIterator >
    379         void TupleAssignSpotter::Options::lift_intersection( InputIterator begin, InputIterator end, OutputIterator out ) {
    380                 if ( begin == end ) return;
    381                 InputIterator test = begin;
    382 
    383                 if (++test == end)
    384                         { copy(begin->begin(), begin->end(), out); return; }
    385 
    386 
    387                 std::multiset<int> cur; // InputIterator::value_type::value_type
    388                 copy( begin->begin(), begin->end(), inserter( cur, cur.begin() ) );
    389 
    390                 while ( test != end ) {
    391                         std::multiset<int> temp;
    392                         set_intersection( cur.begin(), cur.end(), test->begin(), test->end(), inserter(temp,temp.begin()) );
    393                         cur.clear();
    394                         copy( temp.begin(), temp.end(), inserter(cur,cur.begin()));
    395                         ++test;
    396                 }
    397 
    398                 copy( cur.begin(), cur.end(), out );
    399                 return;
    400         }
    401 
    402         ResolvExpr::AltList TupleAssignSpotter::Options::get_option( std::list< ResolvExpr::AltList >::size_type index ) {
    403                 if ( index >= options.size() )
    404                         throw 0; // XXX
    405                 std::list< ResolvExpr::AltList >::iterator it = options.begin();
    406                 for ( std::list< ResolvExpr::AltList >::size_type i = 0; i < index; ++i, ++it );
    407                 return *it;
     244                        std::list< ObjectDecl * > ltmp;
     245                        std::list< ObjectDecl * > rtmp;
     246                        std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( ResolvExpr::Alternative & alt ){
     247                                return newObject( lhsNamer, alt.expr );
     248                        });
     249                        std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( ResolvExpr::Alternative & alt ){
     250                                return newObject( rhsNamer, alt.expr );
     251                        });
     252                        zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), [&](ObjectDecl * obj1, ObjectDecl * obj2 ) { return createFunc(spotter.fname, obj1, obj2); } );
     253                        tmpDecls.splice( tmpDecls.end(), ltmp );
     254                        tmpDecls.splice( tmpDecls.end(), rtmp );
     255                }
    408256        }
    409257} // namespace Tuples
Note: See TracChangeset for help on using the changeset viewer.