Changeset 4b6ef70 for src/Tuples
- Timestamp:
- Oct 20, 2017, 11:45:53 AM (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:
- 1fdfc23
- Parents:
- b5a8ef7
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleAssignment.cc
rb5a8ef7 r4b6ef70 20 20 #include <memory> // for unique_ptr, allocator_trai... 21 21 #include <string> // for string 22 #include <vector>23 22 24 23 #include "CodeGen/OperatorTable.h" … … 43 42 #include "SynTree/Visitor.h" // for Visitor 44 43 44 #if 0 45 #define PRINT(x) x 46 #else 47 #define PRINT(x) 48 #endif 49 45 50 namespace Tuples { 46 51 class TupleAssignSpotter { … … 55 60 struct Matcher { 56 61 public: 57 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const 58 ResolvExpr::AltList& rhs ); 62 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 59 63 virtual ~Matcher() {} 60 64 virtual void match( std::list< Expression * > &out ) = 0; … … 69 73 struct MassAssignMatcher : public Matcher { 70 74 public: 71 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 72 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 75 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 73 76 virtual void match( std::list< Expression * > &out ); 74 77 }; … … 76 79 struct MultipleAssignMatcher : public Matcher { 77 80 public: 78 MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 79 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {} 81 MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts ); 80 82 virtual void match( std::list< Expression * > &out ); 81 83 }; … … 89 91 bool isTuple( Expression *expr ) { 90 92 if ( ! expr ) return false; 91 assert( expr-> has_result());93 assert( expr->result ); 92 94 return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() ); 93 95 } … … 114 116 115 117 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, 116 117 118 118 std::vector<ResolvExpr::AlternativeFinder> &args ) { 119 TupleAssignSpotter spotter( currentFinder ); 120 spotter.spot( expr, args ); 119 121 } 120 122 … … 122 124 : currentFinder(f) {} 123 125 124 void TupleAssignSpotter::spot( UntypedExpr * expr, 125 std::vector<ResolvExpr::AlternativeFinder> &args ) { 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 126 130 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { 127 131 if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) { 128 fname = op->get_name(); 129 130 // AlternativeFinder will naturally handle this case case, if it's legal 131 if ( args.size() == 0 ) return; 132 133 // if an assignment only takes 1 argument, that's odd, but maybe someone wrote 134 // the function, in which case AlternativeFinder will handle it normally 135 if ( args.size() == 1 && CodeGen::isAssignment( fname ) ) return; 136 137 // look over all possible left-hand-sides 138 for ( ResolvExpr::Alternative& lhsAlt : args[0] ) { 139 // skip non-tuple LHS 140 if ( ! refToTuple(lhsAlt.expr) ) continue; 141 142 // explode is aware of casts - ensure every LHS expression is sent into explode 143 // with a reference cast 144 // xxx - this seems to change the alternatives before the normal 145 // AlternativeFinder flow; maybe this is desired? 146 if ( ! dynamic_cast<CastExpr*>( lhsAlt.expr ) ) { 147 lhsAlt.expr = new CastExpr( lhsAlt.expr, 148 new ReferenceType( Type::Qualifiers(), 149 lhsAlt.expr->get_result()->clone() ) ); 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; 150 139 } 151 140 152 // explode the LHS so that each field of a tuple-valued-expr is assigned 153 ResolvExpr::AltList lhs; 154 explode( lhsAlt, currentFinder.get_indexer(), back_inserter(lhs), true ); 155 for ( ResolvExpr::Alternative& alt : lhs ) { 156 // each LHS value must be a reference - some come in with a cast expression, 157 // if not just cast to reference here 158 if ( ! dynamic_cast<ReferenceType*>( alt.expr->get_result() ) ) { 159 alt.expr = new CastExpr( alt.expr, 160 new ReferenceType( Type::Qualifiers(), 161 alt.expr->get_result()->clone() ) ); 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 ) ); 162 155 } 163 } 164 165 if ( args.size() > 2 ) { 166 // expand all possible RHS possibilities 167 // TODO build iterative version of this instead of using combos 168 std::vector< ResolvExpr::AltList > rhsAlts; 169 combos( std::next(args.begin(), 1), args.end(), 170 std::back_inserter( rhsAlts ) ); 171 for ( const ResolvExpr::AltList& rhsAlt : rhsAlts ) { 172 // multiple assignment 173 ResolvExpr::AltList rhs; 174 explode( rhsAlt, currentFinder.get_indexer(), 175 std::back_inserter(rhs), true ); 176 matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) ); 177 match(); 178 } 179 } else { 180 for ( const ResolvExpr::Alternative& rhsAlt : args[1] ) { 181 ResolvExpr::AltList rhs; 182 if ( isTuple(rhsAlt.expr) ) { 183 // multiple assignment 184 explode( rhsAlt, currentFinder.get_indexer(), 185 std::back_inserter(rhs), true ); 186 matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) ); 187 } else { 188 // mass assignment 189 rhs.push_back( rhsAlt ); 190 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) ); 191 } 192 match(); 193 } 156 match(); 194 157 } 195 158 } … … 212 175 // now resolve new assignments 213 176 for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) { 177 PRINT( 178 std::cerr << "== resolving tuple assign ==" << std::endl; 179 std::cerr << *i << std::endl; 180 ) 181 214 182 ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() ); 215 183 try { … … 236 204 } 237 205 238 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, 239 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs ) 240 : lhs(lhs), rhs(rhs), spotter(spotter), 241 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {} 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 ); 238 } 242 239 243 240 UntypedExpr * createFunc( const std::string &fname, ObjectDecl *left, ObjectDecl *right ) { … … 262 259 263 260 ObjectDecl * TupleAssignSpotter::Matcher::newObject( UniqueName & namer, Expression * expr ) { 264 assert( expr-> has_result()&& ! expr->get_result()->isVoid() );261 assert( expr->result && ! expr->get_result()->isVoid() ); 265 262 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) ); 266 263 // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient. … … 272 269 ctorInit->accept( rm ); 273 270 } 271 PRINT( std::cerr << "new object: " << ret << std::endl; ) 274 272 return ret; 275 273 }
Note: See TracChangeset
for help on using the changeset viewer.