| 1 | //
 | 
|---|
| 2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
 | 
|---|
| 3 | //
 | 
|---|
| 4 | // The contents of this file are covered under the licence agreement in the
 | 
|---|
| 5 | // file "LICENCE" distributed with Cforall.
 | 
|---|
| 6 | //
 | 
|---|
| 7 | // TupleAssignment.cc -- 
 | 
|---|
| 8 | //
 | 
|---|
| 9 | // Author           : Rodolfo G. Esteves
 | 
|---|
| 10 | // 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
 | 
|---|
| 13 | // Update Count     : 2
 | 
|---|
| 14 | //
 | 
|---|
| 15 | 
 | 
|---|
| 16 | #include "ResolvExpr/AlternativeFinder.h"
 | 
|---|
| 17 | #include "ResolvExpr/Alternative.h"
 | 
|---|
| 18 | #include "ResolvExpr/typeops.h"
 | 
|---|
| 19 | #include "SynTree/Expression.h"
 | 
|---|
| 20 | #include "TupleAssignment.h"
 | 
|---|
| 21 | #include "Common/SemanticError.h"
 | 
|---|
| 22 | 
 | 
|---|
| 23 | #include <functional>
 | 
|---|
| 24 | #include <algorithm>
 | 
|---|
| 25 | #include <iterator>
 | 
|---|
| 26 | #include <iostream>
 | 
|---|
| 27 | #include <cassert>
 | 
|---|
| 28 | #include <set>
 | 
|---|
| 29 | 
 | 
|---|
| 30 | namespace Tuples {
 | 
|---|
| 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 |                                   }*/
 | 
|---|
| 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
 | 
|---|
| 150 |                                                         // 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() ) );
 | 
|---|
| 178 |                                                 }
 | 
|---|
| 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() ) );
 | 
|---|
| 189 |                                         }
 | 
|---|
| 190 |                                 }
 | 
|---|
| 191 |                         }
 | 
|---|
| 192 |                 }
 | 
|---|
| 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
 | 
|---|
| 267 |                 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;
 | 
|---|
| 408 |         }
 | 
|---|
| 409 | } // namespace Tuples
 | 
|---|
| 410 | 
 | 
|---|
| 411 | // Local Variables: //
 | 
|---|
| 412 | // tab-width: 4 //
 | 
|---|
| 413 | // mode: c++ //
 | 
|---|
| 414 | // compile-command: "make install" //
 | 
|---|
| 415 | // End: //
 | 
|---|