Changeset 65660bd for src/Tuples/TupleAssignment.cc
- Timestamp:
- Sep 22, 2016, 8:14:56 AM (8 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:
- ac9ca96
- Parents:
- 1132b62
- git-author:
- Rob Schluntz <rschlunt@…> (09/21/16 23:43:37)
- git-committer:
- Rob Schluntz <rschlunt@…> (09/22/16 08:14:56)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleAssignment.cc
r1132b62 r65660bd 21 21 #include "Tuples.h" 22 22 #include "Common/SemanticError.h" 23 #include "InitTweak/InitTweak.h" 23 24 24 25 #include <functional> … … 35 36 // dispatcher for Tuple (multiple and mass) assignment operations 36 37 TupleAssignSpotter( ResolvExpr::AlternativeFinder & ); 37 void spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities );38 void spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ); 38 39 39 40 private: … … 42 43 struct Matcher { 43 44 public: 44 Matcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );45 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 45 46 virtual ~Matcher() {} 46 47 virtual void match( std::list< Expression * > &out ) = 0; … … 52 53 struct MassAssignMatcher : public Matcher { 53 54 public: 54 MassAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );55 MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ); 55 56 virtual void match( std::list< Expression * > &out ); 56 57 }; … … 58 59 struct MultipleAssignMatcher : public Matcher { 59 60 public: 60 MultipleAssignMatcher( TupleAssignSpotter &spot, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );61 MultipleAssignMatcher( TupleAssignSpotter &spot, const ResolvExpr::AltList & alts ); 61 62 virtual void match( std::list< Expression * > &out ); 62 63 }; 63 64 64 65 ResolvExpr::AlternativeFinder ¤tFinder; 65 // Expression *rhs, *lhs;66 Matcher *matcher = nullptr;66 std::string fname; 67 std::unique_ptr< Matcher > matcher; 67 68 }; 68 69 … … 74 75 } 75 76 77 template< typename AltIter > 78 bool isMultAssign( AltIter begin, AltIter end ) { 79 // multiple assignment if more than one alternative in the range or if 80 // the alternative is a tuple 81 if ( begin == end ) return false; 82 if ( isTuple( begin->expr ) ) return true; 83 return ++begin != end; 84 } 85 76 86 bool pointsToTuple( Expression *expr ) { 77 87 // also check for function returning tuple of reference types 78 if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) { 88 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 89 return pointsToTuple( castExpr->get_arg() ); 90 } else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) { 79 91 return isTuple( addr->get_arg() ); 80 92 } … … 82 94 } 83 95 84 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {96 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 85 97 TupleAssignSpotter spotter( currentFinder ); 86 98 spotter.spot( expr, possibilities ); … … 90 102 : currentFinder(f) {} 91 103 92 void TupleAssignSpotter::spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) { 93 if ( NameExpr *assgnop = dynamic_cast< NameExpr * >(expr->get_function()) ) { 94 if ( assgnop->get_name() == "?=?" ) { 95 for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 96 if ( ali->size() != 2 ) continue; // what does it mean if an assignment takes >2 arguments? grab args 2-N and group into a TupleExpr, then proceed? 97 ResolvExpr::Alternative & alt1 = ali->front(), & alt2 = ali->back(); 98 104 void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 105 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { 106 if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) { 107 fname = op->get_name(); 108 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 109 if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal 110 if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) { 111 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it 112 continue; 113 } 114 115 assert( ! ali->empty() ); 116 // grab args 2-N and group into a TupleExpr 117 const ResolvExpr::Alternative & alt1 = ali->front(); 118 auto begin = std::next(ali->begin(), 1), end = ali->end(); 99 119 if ( pointsToTuple(alt1.expr) ) { 100 MultipleAssignMatcher multiMatcher( *this, alt1, alt2 ); 101 MassAssignMatcher massMatcher( *this, alt1, alt2 ); 102 if ( isTuple( alt2.expr ) ) { 103 matcher = &multiMatcher; 120 if ( isMultAssign( begin, end ) ) { 121 matcher.reset( new MultipleAssignMatcher( *this, *ali ) ); 104 122 } else { 105 123 // mass assignment 106 matcher = &massMatcher;124 matcher.reset( new MassAssignMatcher( *this, *ali ) ); 107 125 } 108 126 match(); 109 } else if ( isTuple( alt2.expr ) ) {110 throw SemanticError("Cannot assign a tuple value into a non-tuple lvalue.", expr);111 127 } 112 128 } … … 146 162 } 147 163 148 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : spotter(spotter) { 149 if (AddressExpr *addr = dynamic_cast<AddressExpr *>(lhs.expr) ) { 150 // xxx - not every assignment NEEDS to have the first argument as address-taken, e.g. a manual call to assignment. What to do in this case? skip it as a possibility for TupleAssignment, since the type will always be T*, where T can never be a tuple? Is this true? 151 152 // explode the lhs so that each field of the tuple-valued-expr is assigned. 153 ResolvExpr::Alternative lhsAlt( addr->get_arg()->clone(), lhs.env, lhs.cost, lhs.cvtCost ); 154 explode( lhsAlt, back_inserter(this->lhs) ); 155 } 156 } 157 158 TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : Matcher( spotter, lhs, rhs ) { 159 this->rhs.push_back( rhs ); 160 } 161 162 TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : Matcher( spotter, lhs, rhs ) { 163 164 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList &alts ) : spotter(spotter) { 165 assert( ! alts.empty() ); 166 ResolvExpr::Alternative lhsAlt = alts.front(); 167 // peel off the cast that exists on ctor/dtor expressions 168 bool isCast = false; 169 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( lhsAlt.expr ) ) { 170 lhsAlt.expr = castExpr->get_arg(); 171 castExpr->set_arg( nullptr ); 172 delete castExpr; 173 isCast = true; 174 } 175 176 // explode the lhs so that each field of the tuple-valued-expr is assigned. 177 explode( lhsAlt, back_inserter(lhs) ); 178 // and finally, re-add the cast to each lhs expr, so that qualified tuple fields can be constructed 179 if ( isCast ) { 180 for ( ResolvExpr::Alternative & alt : lhs ) { 181 Expression *& expr = alt.expr; 182 Type * castType = expr->get_result()->clone(); 183 Type * type = InitTweak::getPointerBase( castType ); 184 assert( type ); 185 type->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true); 186 type->set_isLvalue( true ); // xxx - might not need this 187 expr = new CastExpr( expr, castType ); 188 } 189 } 190 // } 191 } 192 193 TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter,const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) { 194 assert( alts.size() == 1 || alts.size() == 2 ); 195 if ( alts.size() == 2 ) { 196 rhs.push_back( alts.back() ); 197 } 198 } 199 200 TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) { 164 201 // explode the rhs so that each field of the tuple-valued-expr is assigned. 165 explode( rhs, back_inserter(this->rhs) );166 } 167 168 UntypedExpr * create Assgn(ObjectDecl *left, ObjectDecl *right ) {169 assert( left && right);202 explode( std::next(alts.begin(), 1), alts.end(), back_inserter(rhs) ); 203 } 204 205 UntypedExpr * createFunc( const std::string &fname, ObjectDecl *left, ObjectDecl *right ) { 206 assert( left ); 170 207 std::list< Expression * > args; 171 208 args.push_back( new AddressExpr( new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ new VariableExpr( left ) } ) ) ); 172 args.push_back( new VariableExpr( right ) ); 173 return new UntypedExpr( new NameExpr( "?=?" ), args ); 209 // args.push_back( new AddressExpr( new VariableExpr( left ) ) ); 210 if ( right ) args.push_back( new VariableExpr( right ) ); 211 return new UntypedExpr( new NameExpr( fname ), args ); 174 212 } 175 213 … … 182 220 static UniqueName lhsNamer( "__massassign_L" ); 183 221 static UniqueName rhsNamer( "__massassign_R" ); 184 assert ( ! lhs.empty() && rhs.size() == 1);185 186 ObjectDecl * rtmp = newObject( rhsNamer, rhs.front().expr );222 assert ( ! lhs.empty() && rhs.size() <= 1); 223 224 ObjectDecl * rtmp = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr; 187 225 for ( ResolvExpr::Alternative & lhsAlt : lhs ) { 188 ObjectDecl * ltmp = newObject( lhsNamer, new AddressExpr( lhsAlt.expr ));189 out.push_back( create Assgn(ltmp, rtmp ) );226 ObjectDecl * ltmp = newObject( lhsNamer, lhsAlt.expr ); 227 out.push_back( createFunc( spotter.fname, ltmp, rtmp ) ); 190 228 tmpDecls.push_back( ltmp ); 191 229 } 192 tmpDecls.push_back( rtmp );230 if ( rtmp ) tmpDecls.push_back( rtmp ); 193 231 } 194 232 … … 201 239 std::list< ObjectDecl * > rtmp; 202 240 std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( ResolvExpr::Alternative & alt ){ 203 return newObject( lhsNamer, new AddressExpr( alt.expr ));241 return newObject( lhsNamer, alt.expr ); 204 242 }); 205 243 std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( ResolvExpr::Alternative & alt ){ 206 244 return newObject( rhsNamer, alt.expr ); 207 245 }); 208 zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), createAssgn);246 zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), [&](ObjectDecl * obj1, ObjectDecl * obj2 ) { return createFunc(spotter.fname, obj1, obj2); } ); 209 247 tmpDecls.splice( tmpDecls.end(), ltmp ); 210 248 tmpDecls.splice( tmpDecls.end(), rtmp );
Note: See TracChangeset
for help on using the changeset viewer.