Ignore:
Timestamp:
May 18, 2015, 11:45:33 PM (9 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, string, with_gc
Children:
01aeade
Parents:
0dd3a2f
Message:

licencing: fourth groups of files

File:
1 edited

Legend:

Unmodified
Added
Removed
  • translator/Tuples/TupleAssignment.cc

    r0dd3a2f r51587aa  
     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           : Richard C. Bilson
     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
    116#include "ResolvExpr/AlternativeFinder.h"
    217#include "ResolvExpr/Alternative.h"
     
    1429
    1530namespace Tuples {
    16   TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder *f = 0 )
    17     : currentFinder(f), matcher(0), hasMatched( false ) {}
    18 
    19   bool TupleAssignSpotter::pointsToTuple( Expression *expr ) {
    20     // also check for function returning tuple of reference types
    21     if (AddressExpr *addr = dynamic_cast<AddressExpr *>(expr) )
    22       if ( isTuple(addr->get_arg() ) )
    23         return true;
    24     return false;
    25   }
    26 
    27   bool TupleAssignSpotter::isTupleVar( DeclarationWithType *decl ) {
    28     if ( dynamic_cast<TupleType *>(decl->get_type()) )
    29       return true;
    30     return false;
    31   }
    32 
    33   bool TupleAssignSpotter::isTuple( Expression *expr, bool isRight ) {
    34     // true if `expr' is an expression returning a tuple: tuple, tuple variable or MRV function
    35     if ( ! expr ) return false;
    36 
    37     if ( dynamic_cast<TupleExpr *>(expr) )
    38       return true;
    39     else if ( VariableExpr *var = dynamic_cast<VariableExpr *>(expr) ) {
    40       if ( isTupleVar(var->get_var()) )
    41         return true;
    42     }
    43 
    44     return false;
    45   }
    46 
    47   bool TupleAssignSpotter::match() {
    48     assert ( matcher != 0 );
    49 
    50     std::list< Expression * > new_assigns;
    51     if (! matcher->match(new_assigns) )
    52       return false;
    53 
    54     if ( new_assigns.empty() ) return false;
    55     /*return */matcher->solve( new_assigns );
    56     if ( dynamic_cast<TupleAssignSpotter::MultipleAssignMatcher *>( matcher ) ) {
    57       // now resolve new assignments
    58       std::list< Expression * > solved_assigns;
    59       ResolvExpr::AltList solved_alts;
    60       assert( currentFinder != 0 );
    61 
    62       ResolvExpr::AltList current;
    63       for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
    64         //try {
    65         ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
    66         finder.findWithAdjustment(*i);
    67         // prune expressions that don't coincide with
    68         ResolvExpr::AltList alts = finder.get_alternatives();
    69         assert( alts.size() == 1 );
    70         assert(alts.front().expr != 0 );
    71         current.push_back( finder.get_alternatives().front() );
    72         solved_assigns.push_back( alts.front().expr->clone() );
    73         //solved_assigns.back()->print(std::cerr);
    74         /*} catch( ... ) {
    75           continue; // no reasonable alternative found
    76           }*/
    77       }
    78       options.add_option( current );
    79 
    80       return true;
    81     } else { // mass assignment
    82       //if ( new_assigns.empty() ) return false;
    83       std::list< Expression * > solved_assigns;
    84       ResolvExpr::AltList solved_alts;
    85       assert( currentFinder != 0 );
    86 
    87       ResolvExpr::AltList current;
    88       if ( optMass.empty() ) {
    89         for ( std::list< Expression * >::size_type i = 0; i != new_assigns.size(); ++i )
    90           optMass.push_back( ResolvExpr::AltList() );
    91       }
    92       int cnt = 0;
    93       for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i, cnt++ ) {
    94 
    95         ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
    96         finder.findWithAdjustment(*i);
    97         ResolvExpr::AltList alts = finder.get_alternatives();
    98         assert( alts.size() == 1 );
    99         assert(alts.front().expr != 0 );
    100         current.push_back( finder.get_alternatives().front() );
    101         optMass[cnt].push_back( finder.get_alternatives().front() );
    102         solved_assigns.push_back( alts.front().expr->clone() );
    103       }
    104 
    105       return true;
    106     }
    107 
    108     return false;
    109   }
    110 
    111   bool TupleAssignSpotter::isMVR( Expression *expr ) {
    112     if ( expr->get_results().size() > 1 ) {
    113       // MVR processing
    114       return true;
    115     }
    116     return false;
    117   }
    118 
    119   bool TupleAssignSpotter::isTupleAssignment( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
    120     if (  NameExpr *assgnop = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    121 
    122       if ( assgnop->get_name() == std::string("?=?") ) {
    123 
    124         for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    125           assert( ali->size() == 2 );
    126           ResolvExpr::AltList::iterator opit = ali->begin();
    127           ResolvExpr::Alternative op1 = *opit, op2 = *(++opit);
    128 
    129           if ( pointsToTuple(op1.expr) ) { // also handles tuple vars
    130             if ( isTuple( op2.expr, true ) )
    131               matcher = new MultipleAssignMatcher(op1.expr, op2.expr);
    132             else if ( isMVR( op2.expr ) ) {
    133               // handle MVR differently
    134             } else
    135               // mass assignment
    136               matcher = new MassAssignMatcher(op1.expr, op2.expr);
    137 
    138             std::list< ResolvExpr::AltList > options;
    139             if ( match() )
    140               /*
    141               if ( hasMatched ) {
    142                 // throw SemanticError("Ambiguous tuple assignment");
    143               } else {*/
    144                 // Matched for the first time
    145                 hasMatched = true;
    146                 /*} */
    147           } /* else if ( isTuple( op2 ) )
    148             throw SemanticError("Inapplicable tuple assignment.");
    149             */
    150         }
    151 
    152         if ( hasMatched ) {
    153           if ( dynamic_cast<TupleAssignSpotter::MultipleAssignMatcher *>( matcher ) ) {
    154             //options.print( std::cerr );
    155             std::list< ResolvExpr::AltList >best = options.get_best();
    156             if ( best.size() == 1 ) {
    157               std::list<Expression *> solved_assigns;
    158               for ( ResolvExpr::AltList::iterator i = best.front().begin(); i != best.front().end(); ++i ){
    159                 solved_assigns.push_back( i->expr );
    160               }
    161               /* assigning cost zero? */
    162               currentFinder->get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns/*, SolvedTupleExpr::MULTIPLE*/), currentFinder->get_environ(), ResolvExpr::Cost() ) );
    163             }
    164           } else {
    165             assert(! optMass.empty() );
    166             ResolvExpr::AltList winners;
    167             for ( std::vector< ResolvExpr::AltList >::iterator i = optMass.begin(); i != optMass.end(); ++i )
    168               findMinCostAlt( i->begin(), i->end(), back_inserter(winners) );
    169 
    170             std::list< Expression *> solved_assigns;
    171             for ( ResolvExpr::AltList::iterator i = winners.begin(); i != winners.end(); ++i )
    172               solved_assigns.push_back( i->expr );
    173             currentFinder->get_alternatives().push_front( ResolvExpr::Alternative(new SolvedTupleExpr(solved_assigns/*, SolvedTupleExpr::MASS*/), currentFinder->get_environ(), ResolvExpr::Cost() ) );
    174           }
    175         }
    176       }
    177     }
    178     return hasMatched;
    179   }
    180 
    181   void TupleAssignSpotter::Matcher::init( Expression *_lhs, Expression *_rhs ) {
    182     lhs.clear();
    183     if (AddressExpr *addr = dynamic_cast<AddressExpr *>(_lhs) )
    184       if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(addr->get_arg()) )
    185         std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(lhs) );
    186 
    187     rhs.clear();
    188   }
    189 
    190   TupleAssignSpotter::Matcher::Matcher( /*TupleAssignSpotter &spot,*/ Expression *_lhs, Expression *_rhs ) /*: own_spotter(spot) */{
    191     init(_lhs,_rhs);
    192   }
    193 
    194   TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( Expression *_lhs, Expression *_rhs )/* : own_spotter(spot) */{
    195     init(_lhs,_rhs);
    196 
    197     if ( TupleExpr *tuple = dynamic_cast<TupleExpr *>(_rhs) )
    198       std::copy( tuple->get_exprs().begin(), tuple->get_exprs().end(), back_inserter(rhs) );
    199   }
    200 
    201   UntypedExpr *TupleAssignSpotter::Matcher::createAssgn( Expression *left, Expression *right ) {
    202     if ( left && right ) {
    203       std::list< Expression * > args;
    204       args.push_back(new AddressExpr(left->clone()));  args.push_back(right->clone());
    205       return new UntypedExpr(new NameExpr("?=?"), args);
    206     } else
    207       throw 0; // xxx - diagnose the problem
    208   }
    209 
    210   bool TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
    211     if ( lhs.empty() || (rhs.size() != 1) ) return false;
    212 
    213     for ( std::list< Expression * >::iterator l = lhs.begin(); l != lhs.end(); l++ ) {
    214       std::list< Expression * > args;
    215       args.push_back( new AddressExpr(*l) );
    216       args.push_back( rhs.front() );
    217       out.push_back( new UntypedExpr(new NameExpr("?=?"), args) );
    218     }
    219 
    220     return true;
    221   }
    222 
    223   bool TupleAssignSpotter::MassAssignMatcher::solve( std::list< Expression * > &assigns ) {
    224     /*
    225     std::list< Expression * > solved_assigns;
    226     ResolvExpr::AltList solved_alts;
    227     assert( currentFinder != 0 );
    228 
    229     ResolvExpr::AltList current;
    230     if ( optMass.empty() ) {
    231       for ( std::list< Expression * >::size_type i = 0; i != new_assigns.size(); ++i )
    232         optMass.push_back( ResolvExpr::AltList() );
    233     }
    234     int cnt = 0;
    235     for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i, cnt++ ) {
    236 
    237       ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
    238       finder.findWithAdjustment(*i);
    239       ResolvExpr::AltList alts = finder.get_alternatives();
    240       assert( alts.size() == 1 );
    241       assert(alts.front().expr != 0 );
    242       current.push_back( finder.get_alternatives().front() );
    243       optMass[cnt].push_back( finder.get_alternatives().front() );
    244       solved_assigns.push_back( alts.front().expr->clone() );
    245     }
    246     */
    247     return true;
    248   }
    249 
    250   bool TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
    251     // need more complicated matching
    252     if ( lhs.size() == rhs.size() ) {
    253       zipWith( lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), back_inserter(out), TupleAssignSpotter::Matcher::createAssgn );
    254       return true;
    255     } //else
    256     //std::cerr << "The length of (left, right) is: (" << lhs.size() << "," << rhs.size() << ")" << std::endl;*/
    257     return false;
    258   }
    259 
    260   bool TupleAssignSpotter::MultipleAssignMatcher::solve( std::list< Expression * > &assigns ) {
    261     /*
    262     std::list< Expression * > solved_assigns;
    263     ResolvExpr::AltList solved_alts;
    264     assert( currentFinder != 0 );
    265 
    266     ResolvExpr::AltList current;
    267     for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
    268       //try {
    269       ResolvExpr::AlternativeFinder finder( currentFinder->get_indexer(), currentFinder->get_environ() );
    270       finder.findWithAdjustment(*i);
    271       // prune expressions that don't coincide with
    272       ResolvExpr::AltList alts = finder.get_alternatives();
    273       assert( alts.size() == 1 );
    274       assert(alts.front().expr != 0 );
    275       current.push_back( finder.get_alternatives().front() );
    276       solved_assigns.push_back( alts.front().expr->clone() );
    277       //solved_assigns.back()->print(std::cerr);
    278       //} catch( ... ) {
    279       //continue; // no reasonable alternative found
    280       //}
    281     }
    282     options.add_option( current );
    283     */
    284 
    285     return true;
    286   }
    287 
    288   void TupleAssignSpotter::Options::add_option( ResolvExpr::AltList &opt ) {
    289     using namespace std;
    290 
    291     options.push_back( opt );
    292     /*
    293       vector< Cost > costs;
    294       costs.reserve( opt.size() );
    295       transform( opt.begin(), opt.end(), back_inserter(costs), ptr_fun(extract_cost) );
    296     */
    297     // transpose matrix
    298     if ( costMatrix.empty() )
    299       for ( unsigned int i = 0; i< opt.size(); ++i)
    300         costMatrix.push_back( vector<ResolvExpr::Cost>() );
    301 
    302     int cnt = 0;
    303     for ( ResolvExpr::AltList::iterator i = opt.begin(); i != opt.end(); ++i, cnt++ )
    304       costMatrix[cnt].push_back( i->cost );
    305 
    306     return;
    307   }
    308 
    309   std::list< ResolvExpr::AltList > TupleAssignSpotter::Options::get_best() {
    310     using namespace std;
    311     using namespace ResolvExpr;
    312     list< ResolvExpr::AltList > ret;
    313     list< multiset<int> > solns;
    314     for ( vector< vector<Cost> >::iterator i = costMatrix.begin(); i != costMatrix.end(); ++i ) {
    315       list<int> current;
    316       findMinCost( i->begin(), i->end(), back_inserter(current) );
    317       solns.push_back( multiset<int>(current.begin(), current.end()) );
    318     }
    319     // need to combine
    320     multiset<int> result;
    321     lift_intersection( solns.begin(), solns.end(), inserter( result, result.begin() ) );
    322     if ( result.size() != 1 )
    323       throw SemanticError("Ambiguous tuple expression");
    324     ret.push_back(get_option( *(result.begin() )));
    325     return ret;
    326   }
    327 
    328   void TupleAssignSpotter::Options::print( std::ostream &ostr ) {
    329     using namespace std;
    330 
    331     for ( vector< vector < ResolvExpr::Cost > >::iterator i = costMatrix.begin(); i != costMatrix.end(); ++i ) {
    332       for ( vector < ResolvExpr::Cost >::iterator j = i->begin(); j != i->end(); ++j )
    333         ostr << *j << " " ;
    334       ostr << std::endl;
    335     }
    336    
    337     return;
    338   }
    339 
    340   ResolvExpr::Cost extract_cost( ResolvExpr::Alternative &alt ) {
    341     return alt.cost;
    342   }
    343 
    344   template< typename InputIterator, typename OutputIterator >
    345   void
    346   TupleAssignSpotter::Options::findMinCost( InputIterator begin, InputIterator end, OutputIterator out )
    347   {
    348     using namespace ResolvExpr;
    349     std::list<int> alternatives;
    350 
    351     // select the alternatives that have the minimum parameter cost
    352     Cost minCost = Cost::infinity;
    353     unsigned int index = 0;
    354     for ( InputIterator i = begin; i != end; ++i, index++ ) {
    355       if ( *i < minCost ) {
    356         minCost = *i;
    357         alternatives.clear();
    358         alternatives.push_back( index );
    359       } else if ( *i == minCost ) {
    360         alternatives.push_back( index );
    361       }
    362     }
    363     std::copy( alternatives.begin(), alternatives.end(), out );
    364   }
    365 
    366   template< class InputIterator, class OutputIterator >
    367   void TupleAssignSpotter::Options::lift_intersection( InputIterator begin, InputIterator end, OutputIterator out ){
    368     if ( begin == end ) return;
    369     InputIterator test = begin;
    370 
    371     if (++test == end)
    372       { copy(begin->begin(), begin->end(), out); return; }
    373 
    374 
    375     std::multiset<int> cur; // InputIterator::value_type::value_type
    376     copy( begin->begin(), begin->end(), inserter( cur, cur.begin() ) );
    377 
    378     while ( test != end ) {
    379       std::multiset<int> temp;
    380       set_intersection( cur.begin(), cur.end(), test->begin(), test->end(), inserter(temp,temp.begin()) );
    381       cur.clear();
    382       copy( temp.begin(), temp.end(), inserter(cur,cur.begin()));
    383       ++test;
    384     }
    385 
    386     copy( cur.begin(), cur.end(), out );
    387     return;
    388   }
    389 
    390 
    391   ResolvExpr::AltList TupleAssignSpotter::Options::get_option( std::list< ResolvExpr::AltList >::size_type index ) {
    392     if ( index >= options.size() )
    393       throw 0; // XXX
    394     std::list< ResolvExpr::AltList >::iterator it = options.begin();
    395     for ( std::list< ResolvExpr::AltList >::size_type i = 0; i < index; ++i, ++it );
    396     return *it;
    397   }
    398 
    399 
     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        }
    400409} // namespace Tuples
     410
     411// Local Variables: //
     412// tab-width: 4 //
     413// mode: c++ //
     414// compile-command: "make install" //
     415// End: //
Note: See TracChangeset for help on using the changeset viewer.