Changeset 65660bd for src/Tuples
- Timestamp:
- Sep 22, 2016, 8:14:56 AM (9 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)
- Location:
- src/Tuples
- Files:
-
- 3 edited
-
TupleAssignment.cc (modified) (11 diffs)
-
TupleExpansion.cc (modified) (3 diffs)
-
Tuples.h (modified) (3 diffs)
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 ); -
src/Tuples/TupleExpansion.cc
r1132b62 r65660bd 49 49 50 50 virtual Type * mutate( TupleType * tupleType ); 51 virtual Type * mutate( FunctionType * ftype );52 51 53 52 virtual CompoundStmt * mutate( CompoundStmt * stmt ) { … … 119 118 delete assnExpr; 120 119 return new StmtExpr( compoundStmt ); 121 }122 123 Type * TupleTypeReplacer::mutate( FunctionType * ftype ) {124 // replace multiple-returning functions with functions which return a tuple125 if ( ftype->get_returnVals().size() > 1 ) {126 TupleType * tupleType = safe_dynamic_cast<TupleType *>( ResolvExpr::extractResultType( ftype ) );127 ObjectDecl * retVal = new ObjectDecl( "__tuple_ret", DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, tupleType, nullptr );128 // xxx - replace all uses of return vals with appropriate tuple index expr129 deleteAll( ftype->get_returnVals() );130 ftype->get_returnVals().clear();131 ftype->get_returnVals().push_back( retVal );132 }133 return Parent::mutate( ftype );134 120 } 135 121 … … 167 153 } 168 154 155 Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs ) { 156 if ( result->isVoid() ) { 157 // void result - don't need to produce a value for cascading - just output a chain of comma exprs 158 assert( ! exprs.empty() ); 159 std::list< Expression * >::const_iterator iter = exprs.begin(); 160 Expression * expr = *iter++; 161 for ( ; iter != exprs.end(); ++iter ) { 162 expr = new CommaExpr( expr, *iter ); 163 } 164 return expr; 165 } else { 166 // typed tuple expression - produce a compound literal which performs each of the expressions 167 // as a distinct part of its initializer - the produced compound literal may be used as part of 168 // another expression 169 std::list< Initializer * > inits; 170 for ( Expression * expr : exprs ) { 171 inits.push_back( new SingleInit( expr ) ); 172 } 173 return new CompoundLiteralExpr( result, new ListInit( inits ) ); 174 } 175 } 176 169 177 Expression * TupleExprExpander::mutate( TupleExpr * tupleExpr ) { 170 assert( tupleExpr->get_result() ); 171 std::list< Initializer * > inits; 172 for ( Expression * expr : tupleExpr->get_exprs() ) { 173 inits.push_back( new SingleInit( expr ) ); 174 } 175 return new CompoundLiteralExpr( tupleExpr->get_result(), new ListInit( inits ) ); 176 } 177 178 TupleType * makeTupleType( const std::list< Expression * > & exprs ) { 178 Type * result = tupleExpr->get_result(); 179 std::list< Expression * > exprs = tupleExpr->get_exprs(); 180 assert( result ); 181 182 tupleExpr->set_result( nullptr ); 183 tupleExpr->get_exprs().clear(); 184 delete tupleExpr; 185 186 return replaceTupleExpr( result, exprs ); 187 } 188 189 Type * makeTupleType( const std::list< Expression * > & exprs ) { 190 // produce the TupleType which aggregates the types of the exprs 179 191 TupleType *tupleType = new TupleType( Type::Qualifiers(true, true, true, true, true, false) ); 180 192 Type::Qualifiers &qualifiers = tupleType->get_qualifiers(); 181 193 for ( Expression * expr : exprs ) { 182 194 assert( expr->get_result() ); 195 if ( expr->get_result()->isVoid() ) { 196 // if the type of any expr is void, the type of the entire tuple is void 197 delete tupleType; 198 return new VoidType( Type::Qualifiers() ); 199 } 183 200 Type * type = expr->get_result()->clone(); 184 201 tupleType->get_types().push_back( type ); 202 // the qualifiers on the tuple type are the qualifiers that exist on all component types 185 203 qualifiers &= type->get_qualifiers(); 186 204 } // for 187 205 return tupleType; 206 } 207 208 namespace { 209 /// determines if impurity (read: side-effects) may exist in a piece of code. Currently gives a very crude approximation, wherein any function call expression means the code may be impure 210 class ImpurityDetector : public Visitor { 211 public: 212 typedef Visitor Parent; 213 virtual void visit( ApplicationExpr * appExpr ) { maybeImpure = true; } 214 virtual void visit( UntypedExpr * untypedExpr ) { maybeImpure = true; } 215 bool maybeImpure = false; 216 }; 217 } // namespace 218 219 bool maybeImpure( Expression * expr ) { 220 ImpurityDetector detector; 221 expr->accept( detector ); 222 return detector.maybeImpure; 188 223 } 189 224 } // namespace Tuples -
src/Tuples/Tuples.h
r1132b62 r65660bd 15 15 16 16 #ifndef _TUPLES_H_ 17 #define _TUPLE _H_17 #define _TUPLES_H_ 18 18 19 19 #include <string> … … 27 27 namespace Tuples { 28 28 // TupleAssignment.cc 29 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, std::list<ResolvExpr::AltList> & possibilities );29 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, const std::list<ResolvExpr::AltList> & possibilities ); 30 30 31 31 // TupleExpansion.cc … … 34 34 void expandUniqueExpr( std::list< Declaration * > & translationUnit ); 35 35 36 TupleType * makeTupleType( const std::list< Expression * > & exprs ); 36 /// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types 37 Type * makeTupleType( const std::list< Expression * > & exprs ); 38 39 bool maybeImpure( Expression * expr ); 40 41 42 /// helper function used by explode 43 template< typename OutputIterator > 44 void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, OutputIterator out ) { 45 Type * res = expr->get_result(); 46 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) { 47 ResolvExpr::AltList alts; 48 explodeUnique( addrExpr->get_arg(), alt, back_inserter( alts ) ); 49 for ( ResolvExpr::Alternative & alt : alts ) { 50 // distribute '&' over all components 51 alt.expr = new AddressExpr( alt.expr ); 52 *out++ = alt; 53 } 54 } else if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) { 55 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) { 56 // can open tuple expr and dump its exploded components 57 for ( Expression * expr : tupleExpr->get_exprs() ) { 58 explodeUnique( expr, alt, out ); 59 } 60 } else { 61 // tuple type, but not tuple expr - recursively index into its components 62 Expression * arg = expr->clone(); 63 if ( Tuples::maybeImpure( arg ) ) { 64 // expressions which may contain side effects require a single unique instance of the expression 65 arg = new UniqueExpr( arg ); 66 } 67 for ( unsigned int i = 0; i < tupleType->size(); i++ ) { 68 TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i ); 69 explodeUnique( idx, alt, out ); 70 delete idx; 71 } 72 delete arg; 73 } 74 } else { 75 // atomic (non-tuple) type - output a clone of the expression in a new alternative 76 *out++ = ResolvExpr::Alternative( expr->clone(), alt.env, alt.cost, alt.cvtCost ); 77 } 78 } 79 80 /// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type 81 template< typename OutputIterator > 82 void explode( const ResolvExpr::Alternative &alt, OutputIterator out ) { 83 explodeUnique( alt.expr, alt, out ); 84 } 85 86 // explode list of alternatives 87 template< typename AltIterator, typename OutputIterator > 88 void explode( AltIterator altBegin, AltIterator altEnd, OutputIterator out ) { 89 for ( ; altBegin != altEnd; ++altBegin ) { 90 explode( *altBegin, out ); 91 } 92 } 93 94 template< typename OutputIterator > 95 void explode( const ResolvExpr::AltList & alts, OutputIterator out ) { 96 explode( alts.begin(), alts.end(), out ); 97 } 37 98 } // namespace Tuples 38 99
Note:
See TracChangeset
for help on using the changeset viewer.