Changes in src/Tuples/Explode.h [c6b4432:7870799]
- File:
-
- 1 edited
-
src/Tuples/Explode.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/Explode.h
rc6b4432 r7870799 20 20 21 21 #include "AST/Expr.hpp" 22 #include "ResolvExpr/Alternative.h" // for Alternative, AltList 22 23 #include "ResolvExpr/Candidate.hpp" // for Candidate, CandidateList 24 #include "ResolvExpr/ExplodedActual.h" // for ExplodedActual 23 25 #include "ResolvExpr/ExplodedArg.hpp" // for ExplodedArg 26 #include "SynTree/Expression.h" // for Expression, UniqueExpr, AddressExpr 27 #include "SynTree/Type.h" // for TupleType, Type 24 28 #include "Tuples.h" // for maybeImpure 25 29 … … 28 32 } 29 33 34 namespace SymTab { 35 class Indexer; 36 } // namespace SymTab 37 30 38 namespace Tuples { 39 Expression * distributeReference( Expression * ); 40 41 static inline CastExpr * isReferenceCast( Expression * expr ) { 42 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 43 if ( dynamic_cast< ReferenceType * >( castExpr->result ) ) { 44 return castExpr; 45 } 46 } 47 return nullptr; 48 } 49 50 /// Append alternative to an OutputIterator of Alternatives 51 template<typename OutputIterator> 52 void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env, 53 const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need, 54 const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) { 55 *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost }; 56 } 57 58 /// Append alternative to an ExplodedActual 59 static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr, 60 const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&, 61 const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) { 62 ea.exprs.emplace_back( expr ); 63 /// xxx -- merge environment, openVars, need, cost? 64 } 65 66 /// helper function used by explode 67 template< typename Output > 68 void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, 69 const SymTab::Indexer & indexer, Output&& out, bool isTupleAssign ) { 70 if ( isTupleAssign ) { 71 // tuple assignment needs CastExprs to be recursively exploded to easily get at all of the components 72 if ( CastExpr * castExpr = isReferenceCast( expr ) ) { 73 ResolvExpr::AltList alts; 74 explodeUnique( 75 castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign ); 76 for ( ResolvExpr::Alternative & alt : alts ) { 77 // distribute reference cast over all components 78 append( std::forward<Output>(out), distributeReference( alt.release_expr() ), 79 alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost ); 80 } 81 // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives) 82 return; 83 } 84 } 85 Type * res = expr->get_result()->stripReferences(); 86 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) { 87 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) { 88 // can open tuple expr and dump its exploded components 89 for ( Expression * expr : tupleExpr->get_exprs() ) { 90 explodeUnique( expr, alt, indexer, std::forward<Output>(out), isTupleAssign ); 91 } 92 } else { 93 // tuple type, but not tuple expr - recursively index into its components. 94 // if expr type is reference, convert to value type 95 Expression * arg = expr->clone(); 96 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 97 // expressions which may contain side effects require a single unique instance of the expression. 98 arg = new UniqueExpr( arg ); 99 } 100 // cast reference to value type to facilitate further explosion 101 if ( dynamic_cast<ReferenceType *>( arg->get_result() ) ) { 102 arg = new CastExpr( arg, tupleType->clone() ); 103 } 104 for ( unsigned int i = 0; i < tupleType->size(); i++ ) { 105 TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i ); 106 explodeUnique( idx, alt, indexer, std::forward<Output>(out), isTupleAssign ); 107 delete idx; 108 } 109 delete arg; 110 } 111 } else { 112 // atomic (non-tuple) type - output a clone of the expression in a new alternative 113 append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need, 114 alt.cost, alt.cvtCost ); 115 } 116 } 117 118 /// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type 119 template< typename Output > 120 void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer, 121 Output&& out, bool isTupleAssign = false ) { 122 explodeUnique( alt.expr, alt, indexer, std::forward<Output>(out), isTupleAssign ); 123 } 124 125 // explode list of alternatives 126 template< typename AltIterator, typename Output > 127 void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer, 128 Output&& out, bool isTupleAssign = false ) { 129 for ( ; altBegin != altEnd; ++altBegin ) { 130 explode( *altBegin, indexer, std::forward<Output>(out), isTupleAssign ); 131 } 132 } 133 134 template< typename Output > 135 void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, Output&& out, 136 bool isTupleAssign = false ) { 137 explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign ); 138 } 31 139 32 140 const ast::Expr * distributeReference( const ast::Expr * ); … … 102 210 } 103 211 // Cast a reference away to a value-type to allow further explosion. 104 if ( local->result.as< ast::ReferenceType >() ) {212 if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) { 105 213 local = new ast::CastExpr{ local, tupleType }; 106 214 } … … 112 220 // delete idx; 113 221 } 222 // delete local; 114 223 } 115 224 } else {
Note:
See TracChangeset
for help on using the changeset viewer.