Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cc

    r6eb8948 r906e24d  
    1818#include "ResolvExpr/typeops.h"
    1919#include "SynTree/Expression.h"
    20 #include "SynTree/Initializer.h"
    21 #include "Tuples.h"
     20#include "TupleAssignment.h"
    2221#include "Common/SemanticError.h"
    2322
     
    2827#include <cassert>
    2928#include <set>
    30 #include <unordered_set>
    3129
    3230namespace Tuples {
    33         class TupleAssignSpotter {
    34           public:
    35                 // dispatcher for Tuple (multiple and mass) assignment operations
    36                 TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
    37                 void spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities );
    38 
    39           private:
    40                 void match();
    41                 // records for assignment generation
    42                 struct Options {
    43                         void print( std::ostream & );
    44                         int size() const { return options.size(); }
    45                         bool empty() const { return options.empty(); }
    46                         typedef std::list< ResolvExpr::AltList >::iterator iterator;
    47                         iterator begin() { return options.begin(); }
    48                         iterator end() { return options.end(); }
    49 
    50                         std::list< ResolvExpr::AltList > options;
    51                 };
    52 
    53                 struct Matcher {
    54                   public:
    55                         Matcher( TupleAssignSpotter &spotter, Expression *_lhs, Expression *_rhs );
    56                         virtual ~Matcher() {}
    57                         virtual void match( std::list< Expression * > &out ) = 0;
    58                         std::list< Expression * > lhs, rhs;
    59                         TupleAssignSpotter &spotter;
    60                         std::list< ObjectDecl * > tmpDecls;
    61                 };
    62 
    63                 struct MassAssignMatcher : public Matcher {
    64                   public:
    65                         MassAssignMatcher( TupleAssignSpotter &spotter, Expression *lhs, Expression *rhs ) : Matcher( spotter, lhs, rhs ) {
    66                                 this->rhs.push_back( rhs );
     31        TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder *f = 0 )
     32                : currentFinder(f), matcher(0), hasMatched( false ) {}
     33
     34        bool TupleAssignSpotter::pointsToTuple( Expression *expr ) {
     35                // 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;
     39                return false;
     40        }
     41
     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                                  }*/
    6792                        }
    68                         virtual void match( std::list< Expression * > &out );
    69                 };
    70 
    71                 struct MultipleAssignMatcher : public Matcher {
    72                   public:
    73                         MultipleAssignMatcher( TupleAssignSpotter &spot, Expression *lhs, Expression *rhs );
    74                         virtual void match( std::list< Expression * > &out );
    75                 };
    76 
    77                 ResolvExpr::AlternativeFinder &currentFinder;
    78                 // Expression *rhs, *lhs;
    79                 Matcher *matcher = nullptr;
    80                 Options options;
    81         };
    82 
    83         bool isTupleVar( DeclarationWithType *decl ) {
    84                 return dynamic_cast< TupleType * >( decl->get_type() );
    85         }
    86 
    87         /// true if expr is an expression of tuple type, i.e. a tuple expression, tuple variable, or MRV (multiple-return-value) function
    88         bool isTuple( Expression *expr ) {
    89                 if ( ! expr ) return false;
    90 
    91                 // xxx - used to include cast to varExpr and call to isTupleVar, but this doesn't seem like it should be necessary
    92                 return dynamic_cast<TupleExpr *>(expr) || expr->get_results().size() > 1;
    93         }
    94 
    95         bool pointsToTuple( Expression *expr ) {
    96                 // also check for function returning tuple of reference types
    97                 if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) {
    98                         return isTuple( addr->get_arg() );
    99                 }
     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
    100123                return false;
    101124        }
    102125
    103         bool isTupleExpr( Expression *expr ) {
    104                 return expr->get_results().size() > 1;
    105         }
    106 
    107         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
    108                 TupleAssignSpotter spotter( currentFinder );
    109                 spotter.spot( expr, possibilities );
    110         }
    111 
    112         TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )
    113                 : currentFinder(f) {}
    114 
    115         void TupleAssignSpotter::spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
     126        bool TupleAssignSpotter::isMVR( Expression *expr ) {
     127                return isTuple( expr );
     128        }
     129
     130        bool TupleAssignSpotter::isTupleAssignment( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
    116131                if (  NameExpr *assgnop = dynamic_cast< NameExpr * >(expr->get_function()) ) {
     132
    117133                        if ( assgnop->get_name() == std::string("?=?") ) {
     134
    118135                                for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    119136                                        assert( ali->size() == 2 );
    120                                         ResolvExpr::Alternative op1 = ali->front(), op2 = ali->back();
    121 
    122                                         MultipleAssignMatcher multiMatcher( *this, op1.expr, op2.expr );
    123                                         MassAssignMatcher massMatcher( *this, op1.expr, op2.expr );
     137                                        ResolvExpr::AltList::iterator opit = ali->begin();
     138                                        ResolvExpr::Alternative op1 = *opit, op2 = *(++opit);
     139
    124140                                        if ( pointsToTuple(op1.expr) ) { // also handles tuple vars
    125                                                 if ( isTuple( op2.expr ) ) {
    126                                                         matcher = &multiMatcher;
    127                                                 } else {
     141                                                if ( isTuple( op2.expr, true ) )
     142                                                        matcher = new MultipleAssignMatcher(op1.expr, op2.expr);
     143                                                else if ( isMVR( op2.expr ) ) {
     144                                                        // handle MVR differently
     145                                                } else
    128146                                                        // mass assignment
    129                                                         matcher = &massMatcher;
     147                                                        matcher = new MassAssignMatcher(op1.expr, op2.expr);
     148
     149                                                std::list< ResolvExpr::AltList > options;
     150                                                if ( match() )
     151                                                        /*
     152                                                          if ( hasMatched ) {
     153                                                          // throw SemanticError("Ambiguous tuple assignment");
     154                                                          } else {*/
     155                                                        // Matched for the first time
     156                                                        hasMatched = true;
     157                                                /*} */
     158                                        } /* else if ( isTuple( op2 ) )
     159                                                 throw SemanticError("Inapplicable tuple assignment.");
     160                                          */
     161                                }
     162
     163                                if ( hasMatched ) {
     164                                        if ( dynamic_cast<TupleAssignSpotter::MultipleAssignMatcher *>( matcher ) ) {
     165                                                //options.print( std::cerr );
     166                                                std::list< ResolvExpr::AltList >best = options.get_best();
     167                                                if ( best.size() == 1 ) {
     168                                                        std::list<Expression *> solved_assigns;
     169                                                        for ( ResolvExpr::AltList::iterator i = best.front().begin(); i != best.front().end(); ++i ) {
     170                                                                solved_assigns.push_back( i->expr );
     171                                                        }
     172                                                        /* assigning cost zero? */
     173                                                        currentFinder->get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns/*, SolvedTupleExpr::MULTIPLE*/), currentFinder->get_environ(), ResolvExpr::Cost() ) );
    130174                                                }
    131                                                 match();
    132                                         } else if ( isTuple( op2.expr ) ) {
    133                                                 throw SemanticError("Cannot assign a tuple value into a non-tuple lvalue.", expr);
     175                                        } else {
     176                                                assert( ! optMass.empty() );
     177                                                ResolvExpr::AltList winners;
     178                                                for ( std::vector< ResolvExpr::AltList >::iterator i = optMass.begin(); i != optMass.end(); ++i )
     179                                                        findMinCostAlt( i->begin(), i->end(), back_inserter(winners) );
     180
     181                                                std::list< Expression *> solved_assigns;
     182                                                for ( ResolvExpr::AltList::iterator i = winners.begin(); i != winners.end(); ++i )
     183                                                        solved_assigns.push_back( i->expr );
     184                                                currentFinder->get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns/*, SolvedTupleExpr::MASS*/), currentFinder->get_environ(), ResolvExpr::Cost() ) );
    134185                                        }
    135186                                }
    136187                        }
    137188                }
    138         }
    139 
    140         void TupleAssignSpotter::match() {
    141                 assert ( matcher != 0 );
    142 
    143                 std::list< Expression * > new_assigns;
    144                 matcher->match( new_assigns );
    145 
    146                 if ( new_assigns.empty() ) return;
    147                 ResolvExpr::AltList current;
    148                 // now resolve new assignments
    149                 for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
    150                         ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
    151                         finder.findWithAdjustment(*i);
    152                         // prune expressions that don't coincide with
    153                         ResolvExpr::AltList alts = finder.get_alternatives();
    154                         assert( alts.size() == 1 );
    155                         assert( alts.front().expr != 0 );
    156                         current.push_back( alts.front() );
    157                 }
    158 
    159                 // extract expressions from the assignment alternatives to produce a list of assignments that
    160                 // together form a single alternative
    161                 std::list< Expression *> solved_assigns;
    162                 for ( ResolvExpr::Alternative & alt : current ) {
    163                         solved_assigns.push_back( alt.expr->clone() );
    164                 }
    165                 // xxx - need to do this??
    166                 // TypeEnvironment compositeEnv;
    167                 // simpleCombineEnvironments( i->begin(), i->end(), compositeEnv );
    168                 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), currentFinder.get_environ(), ResolvExpr::sumCost( current ) ) );
    169         }
    170 
    171         TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, Expression *lhs, Expression *rhs ) : spotter(spotter) {
    172                 // xxx - shouldn't need to be &<tuple-expr>, just &<lvalue-tuple-type>
    173                 if (AddressExpr *addr = dynamic_cast<AddressExpr *>(lhs) )
     189                return hasMatched;
     190        }
     191
     192        void TupleAssignSpotter::Matcher::init( Expression *_lhs, Expression *_rhs ) {
     193                lhs.clear();
     194                if (AddressExpr *addr = dynamic_cast<AddressExpr *>(_lhs) )
    174195                        if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(addr->get_arg()) )
    175                                 std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(this->lhs) );
    176         }
    177 
    178         TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, Expression *lhs, Expression *rhs ) : Matcher( spotter, lhs, rhs ) {
    179 
    180                 if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(rhs) )
    181                         std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(this->rhs) );
    182         }
    183 
    184         UntypedExpr * createAssgn( ObjectDecl *left, ObjectDecl *right ) {
    185                 assert( left && right );
    186                 std::list< Expression * > args;
    187                 args.push_back( new AddressExpr( new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ new VariableExpr( left ) } ) ) );
    188                 args.push_back( new VariableExpr( right ) );
    189                 return new UntypedExpr( new NameExpr( "?=?" ), args );
    190         }
    191 
    192         ObjectDecl * newObject( UniqueName & namer, Expression * expr ) {
    193                 Type * type;
    194                 assert( expr->get_results().size() >= 1 );
    195                 if ( expr->get_results().size() > 1 ) {
    196                         TupleType * tt = new TupleType( Type::Qualifiers() );
    197                         cloneAll( expr->get_results(), tt->get_types() );
    198                         type = tt;
    199                 } else {
    200                         type = expr->get_results().front()->clone();
    201                 }
    202                 return new ObjectDecl( namer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, type, new SingleInit( expr->clone() ) );
    203         }
    204 
    205         void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
    206                 static UniqueName lhsNamer( "__massassign_L" );
    207                 static UniqueName rhsNamer( "__massassign_R" );
    208                 assert ( ! lhs.empty() && rhs.size() == 1);
    209 
    210                 ObjectDecl * rtmp = newObject( rhsNamer, rhs.front() );
    211                 for ( Expression * l : lhs ) {
    212                         ObjectDecl * ltmp = newObject( lhsNamer, new AddressExpr( l ) );
    213                         out.push_back( createAssgn( ltmp, rtmp ) );
    214                         tmpDecls.push_back( ltmp );
    215                 }
    216                 tmpDecls.push_back( rtmp );
    217         }
    218 
    219         void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
    220                 static UniqueName lhsNamer( "__multassign_L" );
    221                 static UniqueName rhsNamer( "__multassign_R" );
    222                 // xxx - need more complicated matching?
     196                                std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(lhs) );
     197
     198                rhs.clear();
     199        }
     200
     201        TupleAssignSpotter::Matcher::Matcher( /*TupleAssignSpotter &spot,*/ Expression *_lhs, Expression *_rhs ) /*: own_spotter(spot) */{
     202                init(_lhs,_rhs);
     203        }
     204
     205        TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( Expression *_lhs, Expression *_rhs )/* : own_spotter(spot) */{
     206                init(_lhs,_rhs);
     207
     208                if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(_rhs) )
     209                        std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(rhs) );
     210        }
     211
     212        UntypedExpr *TupleAssignSpotter::Matcher::createAssgn( Expression *left, Expression *right ) {
     213                if ( left && right ) {
     214                        std::list< Expression * > args;
     215                        args.push_back(new AddressExpr(left->clone()));  args.push_back(right->clone());
     216                        return new UntypedExpr(new NameExpr("?=?"), args);
     217                } else
     218                        throw 0; // xxx - diagnose the problem
     219        }
     220
     221        bool TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
     222                if ( lhs.empty() || (rhs.size() != 1) ) return false;
     223
     224                for ( std::list< Expression * >::iterator l = lhs.begin(); l != lhs.end(); l++ ) {
     225                        std::list< Expression * > args;
     226                        args.push_back( new AddressExpr(*l) );
     227                        args.push_back( rhs.front() );
     228                        out.push_back( new UntypedExpr(new NameExpr("?=?"), args) );
     229                }
     230
     231                return true;
     232        }
     233
     234        bool TupleAssignSpotter::MassAssignMatcher::solve( std::list< Expression * > &assigns ) {
     235                /*
     236                  std::list< Expression * > solved_assigns;
     237                  ResolvExpr::AltList solved_alts;
     238                  assert( currentFinder != 0 );
     239
     240                  ResolvExpr::AltList current;
     241                  if ( optMass.empty() ) {
     242                  for ( std::list< Expression * >::size_type i = 0; i != new_assigns.size(); ++i )
     243                  optMass.push_back( ResolvExpr::AltList() );
     244                  }
     245                  int cnt = 0;
     246                  for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i, cnt++ ) {
     247
     248                  ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
     249                  finder.findWithAdjustment(*i);
     250                  ResolvExpr::AltList alts = finder.get_alternatives();
     251                  assert( alts.size() == 1 );
     252                  assert(alts.front().expr != 0 );
     253                  current.push_back( finder.get_alternatives().front() );
     254                  optMass[cnt].push_back( finder.get_alternatives().front() );
     255                  solved_assigns.push_back( alts.front().expr->clone() );
     256                  }
     257                */
     258                return true;
     259        }
     260
     261        bool TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
     262                // need more complicated matching
    223263                if ( lhs.size() == rhs.size() ) {
    224                         std::list< ObjectDecl * > ltmp;
    225                         std::list< ObjectDecl * > rtmp;
    226                         std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( Expression * expr ){
    227                                 return newObject( lhsNamer, new AddressExpr( expr ) );
    228                         });
    229                         std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( Expression * expr ){
    230                                 return newObject( rhsNamer, expr );
    231                         });
    232                         zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), createAssgn );
    233                         tmpDecls.splice( tmpDecls.end(), ltmp );
    234                         tmpDecls.splice( tmpDecls.end(), rtmp );
    235                 }
     264                        zipWith( lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), back_inserter(out), TupleAssignSpotter::Matcher::createAssgn );
     265                        return true;
     266                } //else
     267                //std::cerr << "The length of (left, right) is: (" << lhs.size() << "," << rhs.size() << ")" << std::endl;*/
     268                return false;
     269        }
     270
     271        bool TupleAssignSpotter::MultipleAssignMatcher::solve( std::list< Expression * > &assigns ) {
     272                /*
     273                  std::list< Expression * > solved_assigns;
     274                  ResolvExpr::AltList solved_alts;
     275                  assert( currentFinder != 0 );
     276
     277                  ResolvExpr::AltList current;
     278                  for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
     279                  //try {
     280                  ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
     281                  finder.findWithAdjustment(*i);
     282                  // prune expressions that don't coincide with
     283                  ResolvExpr::AltList alts = finder.get_alternatives();
     284                  assert( alts.size() == 1 );
     285                  assert(alts.front().expr != 0 );
     286                  current.push_back( finder.get_alternatives().front() );
     287                  solved_assigns.push_back( alts.front().expr->clone() );
     288                  //solved_assigns.back()->print(std::cerr);
     289                  //} catch( ... ) {
     290                  //continue; // no reasonable alternative found
     291                  //}
     292                  }
     293                  options.add_option( current );
     294                */
     295
     296                return true;
     297        }
     298
     299        void TupleAssignSpotter::Options::add_option( ResolvExpr::AltList &opt ) {
     300                using namespace std;
     301
     302                options.push_back( opt );
     303                /*
     304                  vector< Cost > costs;
     305                  costs.reserve( opt.size() );
     306                  transform( opt.begin(), opt.end(), back_inserter(costs), ptr_fun(extract_cost) );
     307                */
     308                // transpose matrix
     309                if ( costMatrix.empty() )
     310                        for ( unsigned int i = 0; i< opt.size(); ++i)
     311                                costMatrix.push_back( vector<ResolvExpr::Cost>() );
     312
     313                int cnt = 0;
     314                for ( ResolvExpr::AltList::iterator i = opt.begin(); i != opt.end(); ++i, cnt++ )
     315                        costMatrix[cnt].push_back( i->cost );
     316
     317                return;
     318        }
     319
     320        std::list< ResolvExpr::AltList > TupleAssignSpotter::Options::get_best() {
     321                using namespace std;
     322                using namespace ResolvExpr;
     323                list< ResolvExpr::AltList > ret;
     324                list< multiset<int> > solns;
     325                for ( vector< vector<Cost> >::iterator i = costMatrix.begin(); i != costMatrix.end(); ++i ) {
     326                        list<int> current;
     327                        findMinCost( i->begin(), i->end(), back_inserter(current) );
     328                        solns.push_back( multiset<int>(current.begin(), current.end()) );
     329                }
     330                // need to combine
     331                multiset<int> result;
     332                lift_intersection( solns.begin(), solns.end(), inserter( result, result.begin() ) );
     333                if ( result.size() != 1 )
     334                        throw SemanticError("Ambiguous tuple expression");
     335                ret.push_back(get_option( *(result.begin() )));
     336                return ret;
    236337        }
    237338
    238339        void TupleAssignSpotter::Options::print( std::ostream &ostr ) {
    239                 for ( ResolvExpr::AltList & l : options ) {
    240                         for ( ResolvExpr::Alternative & alt : l ) {
    241                                 alt.print( ostr );
    242                                 ostr << " ";
    243                         }
     340                using namespace std;
     341
     342                for ( vector< vector < ResolvExpr::Cost > >::iterator i = costMatrix.begin(); i != costMatrix.end(); ++i ) {
     343                        for ( vector < ResolvExpr::Cost >::iterator j = i->begin(); j != i->end(); ++j )
     344                                ostr << *j << " " ;
    244345                        ostr << std::endl;
    245346                } // for
     347                return;
     348        }
     349
     350        ResolvExpr::Cost extract_cost( ResolvExpr::Alternative &alt ) {
     351                return alt.cost;
     352        }
     353
     354        template< typename InputIterator, typename OutputIterator >
     355        void TupleAssignSpotter::Options::findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
     356                using namespace ResolvExpr;
     357                std::list<int> alternatives;
     358
     359                // select the alternatives that have the minimum parameter cost
     360                Cost minCost = Cost::infinity;
     361                unsigned int index = 0;
     362                for ( InputIterator i = begin; i != end; ++i, index++ ) {
     363                        if ( *i < minCost ) {
     364                                minCost = *i;
     365                                alternatives.clear();
     366                                alternatives.push_back( index );
     367                        } else if ( *i == minCost ) {
     368                                alternatives.push_back( index );
     369                        }
     370                }
     371                std::copy( alternatives.begin(), alternatives.end(), out );
     372        }
     373
     374        template< class InputIterator, class OutputIterator >
     375        void TupleAssignSpotter::Options::lift_intersection( InputIterator begin, InputIterator end, OutputIterator out ) {
     376                if ( begin == end ) return;
     377                InputIterator test = begin;
     378
     379                if (++test == end)
     380                        { copy(begin->begin(), begin->end(), out); return; }
     381
     382
     383                std::multiset<int> cur; // InputIterator::value_type::value_type
     384                copy( begin->begin(), begin->end(), inserter( cur, cur.begin() ) );
     385
     386                while ( test != end ) {
     387                        std::multiset<int> temp;
     388                        set_intersection( cur.begin(), cur.end(), test->begin(), test->end(), inserter(temp,temp.begin()) );
     389                        cur.clear();
     390                        copy( temp.begin(), temp.end(), inserter(cur,cur.begin()));
     391                        ++test;
     392                }
     393
     394                copy( cur.begin(), cur.end(), out );
     395                return;
     396        }
     397
     398        ResolvExpr::AltList TupleAssignSpotter::Options::get_option( std::list< ResolvExpr::AltList >::size_type index ) {
     399                if ( index >= options.size() )
     400                        throw 0; // XXX
     401                std::list< ResolvExpr::AltList >::iterator it = options.begin();
     402                for ( std::list< ResolvExpr::AltList >::size_type i = 0; i < index; ++i, ++it );
     403                return *it;
    246404        }
    247405} // namespace Tuples
Note: See TracChangeset for help on using the changeset viewer.