Changeset 78315272
- Timestamp:
- Nov 8, 2017, 4:34:54 PM (7 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 3f7e12cb
- Parents:
- fae6f21
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleAssignment.cc
rfae6f21 r78315272 20 20 #include <memory> // for unique_ptr, allocator_trai... 21 21 #include <string> // for string 22 #include <vector> 22 23 23 24 #include "CodeGen/OperatorTable.h" … … 60 61 struct Matcher { 61 62 public: 62 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 63 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const 64 ResolvExpr::AltList& rhs ); 63 65 virtual ~Matcher() {} 64 66 virtual void match( std::list< Expression * > &out ) = 0; … … 73 75 struct MassAssignMatcher : public Matcher { 74 76 public: 75 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 77 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 78 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 76 79 virtual void match( std::list< Expression * > &out ); 77 80 }; … … 79 82 struct MultipleAssignMatcher : public Matcher { 80 83 public: 81 MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts ); 84 MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 85 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 82 86 virtual void match( std::list< Expression * > &out ); 83 87 }; … … 91 95 bool isTuple( Expression *expr ) { 92 96 if ( ! expr ) return false; 93 assert( expr-> result);97 assert( expr->has_result() ); 94 98 return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() ); 95 99 } … … 116 120 117 121 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, 118 std::vector<ResolvExpr::AlternativeFinder> &args ) {119 TupleAssignSpotter spotter( currentFinder );120 spotter.spot( expr, args );122 std::vector<ResolvExpr::AlternativeFinder> &args ) { 123 TupleAssignSpotter spotter( currentFinder ); 124 spotter.spot( expr, args ); 121 125 } 122 126 … … 124 128 : currentFinder(f) {} 125 129 126 void TupleAssignSpotter::spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args ) { 127 std::list<ResolvExpr::AltList> possibilities; 128 combos( args.begin(), args.end(), back_inserter( possibilities ) ); 129 130 void TupleAssignSpotter::spot( UntypedExpr * expr, 131 std::vector<ResolvExpr::AlternativeFinder> &args ) { 130 132 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { 131 133 if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) { 132 fname = op->get_name(); 133 PRINT( std::cerr << "TupleAssignment: " << fname << std::endl; ) 134 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 135 if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal 136 if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) { 137 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it 138 continue; 134 fname = op->get_name(); 135 136 // AlternativeFinder will naturally handle this case case, if it's legal 137 if ( args.size() == 0 ) return; 138 139 // if an assignment only takes 1 argument, that's odd, but maybe someone wrote 140 // the function, in which case AlternativeFinder will handle it normally 141 if ( args.size() == 1 && CodeGen::isAssignment( fname ) ) return; 142 143 // look over all possible left-hand-sides 144 for ( ResolvExpr::Alternative& lhsAlt : args[0] ) { 145 // skip non-tuple LHS 146 if ( ! refToTuple(lhsAlt.expr) ) continue; 147 148 // explode is aware of casts - ensure every LHS expression is sent into explode 149 // with a reference cast 150 // xxx - this seems to change the alternatives before the normal 151 // AlternativeFinder flow; maybe this is desired? 152 if ( ! dynamic_cast<CastExpr*>( lhsAlt.expr ) ) { 153 lhsAlt.expr = new CastExpr( lhsAlt.expr, 154 new ReferenceType( Type::Qualifiers(), 155 lhsAlt.expr->get_result()->clone() ) ); 139 156 } 140 157 141 assert( ! ali->empty() ); 142 // grab args 2-N and group into a TupleExpr 143 const ResolvExpr::Alternative & alt1 = ali->front(); 144 auto begin = std::next(ali->begin(), 1), end = ali->end(); 145 PRINT( std::cerr << "alt1 is " << alt1.expr << std::endl; ) 146 if ( refToTuple(alt1.expr) ) { 147 PRINT( std::cerr << "and is reference to tuple" << std::endl; ) 148 if ( isMultAssign( begin, end ) ) { 149 PRINT( std::cerr << "possible multiple assignment" << std::endl; ) 150 matcher.reset( new MultipleAssignMatcher( *this, *ali ) ); 151 } else { 152 // mass assignment 153 PRINT( std::cerr << "possible mass assignment" << std::endl; ) 154 matcher.reset( new MassAssignMatcher( *this, *ali ) ); 158 // explode the LHS so that each field of a tuple-valued-expr is assigned 159 ResolvExpr::AltList lhs; 160 explode( lhsAlt, currentFinder.get_indexer(), back_inserter(lhs), true ); 161 for ( ResolvExpr::Alternative& alt : lhs ) { 162 // each LHS value must be a reference - some come in with a cast expression, 163 // if not just cast to reference here 164 if ( ! dynamic_cast<ReferenceType*>( alt.expr->get_result() ) ) { 165 alt.expr = new CastExpr( alt.expr, 166 new ReferenceType( Type::Qualifiers(), 167 alt.expr->get_result()->clone() ) ); 155 168 } 169 } 170 171 if ( args.size() == 1 ) { 172 // mass default-initialization/destruction 173 ResolvExpr::AltList rhs{}; 174 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) ); 156 175 match(); 176 } else if ( args.size() > 2 ) { 177 // expand all possible RHS possibilities 178 // TODO build iterative version of this instead of using combos 179 std::vector< ResolvExpr::AltList > rhsAlts; 180 combos( std::next(args.begin(), 1), args.end(), 181 std::back_inserter( rhsAlts ) ); 182 for ( const ResolvExpr::AltList& rhsAlt : rhsAlts ) { 183 // multiple assignment 184 ResolvExpr::AltList rhs; 185 explode( rhsAlt, currentFinder.get_indexer(), 186 std::back_inserter(rhs), true ); 187 matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) ); 188 match(); 189 } 190 } else { 191 for ( const ResolvExpr::Alternative& rhsAlt : args[1] ) { 192 ResolvExpr::AltList rhs; 193 if ( isTuple(rhsAlt.expr) ) { 194 // multiple assignment 195 explode( rhsAlt, currentFinder.get_indexer(), 196 std::back_inserter(rhs), true ); 197 matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) ); 198 } else { 199 // mass assignment 200 rhs.push_back( rhsAlt ); 201 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) ); 202 } 203 match(); 204 } 157 205 } 158 206 } … … 174 222 ResolvExpr::AltList current; 175 223 // now resolve new assignments 176 for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) { 224 for ( std::list< Expression * >::iterator i = new_assigns.begin(); 225 i != new_assigns.end(); ++i ) { 177 226 PRINT( 178 227 std::cerr << "== resolving tuple assign ==" << std::endl; … … 180 229 ) 181 230 182 ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() ); 231 ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(), 232 currentFinder.get_environ() }; 183 233 try { 184 234 finder.findWithAdjustment(*i); … … 201 251 // combine assignment environments into combined expression environment 202 252 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv ); 203 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, ResolvExpr::sumCost( current ) + matcher->baseCost ) ); 204 } 205 206 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter), baseCost( ResolvExpr::sumCost( alts ) ) { 207 assert( ! alts.empty() ); 208 // combine argument environments into combined expression environment 209 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 210 211 ResolvExpr::Alternative lhsAlt = alts.front(); 212 // explode is aware of casts - ensure every LHS expression is sent into explode with a reference cast 213 if ( ! dynamic_cast< CastExpr * >( lhsAlt.expr ) ) { 214 lhsAlt.expr = new CastExpr( lhsAlt.expr, new ReferenceType( Type::Qualifiers(), lhsAlt.expr->get_result()->clone() ) ); 215 } 216 217 // explode the lhs so that each field of the tuple-valued-expr is assigned. 218 explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs), true ); 219 220 for ( ResolvExpr::Alternative & alt : lhs ) { 221 // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here. 222 if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) { 223 alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) ); 224 } 225 } 226 } 227 228 TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) { 229 assert( alts.size() == 1 || alts.size() == 2 ); 230 if ( alts.size() == 2 ) { 231 rhs.push_back( alts.back() ); 232 } 233 } 234 235 TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) { 236 // explode the rhs so that each field of the tuple-valued-expr is assigned. 237 explode( std::next(alts.begin(), 1), alts.end(), spotter.currentFinder.get_indexer(), back_inserter(rhs), true ); 253 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative( 254 new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 255 ResolvExpr::sumCost( current ) + matcher->baseCost ) ); 256 } 257 258 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, 259 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs ) 260 : lhs(lhs), rhs(rhs), spotter(spotter), 261 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) { 262 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv ); 263 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv ); 238 264 } 239 265 … … 259 285 260 286 ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) { 261 assert( expr-> result&& ! expr->get_result()->isVoid() );287 assert( expr->has_result() && ! expr->get_result()->isVoid() ); 262 288 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) ); 263 289 // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient. … … 269 295 ctorInit->accept( rm ); 270 296 } 271 PRINT( std::cerr << "new object: " << ret << std::endl; )272 297 return ret; 273 298 }
Note: See TracChangeset
for help on using the changeset viewer.