Changeset c6b4432 for src/Tuples


Ignore:
Timestamp:
Nov 8, 2023, 2:01:11 PM (16 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
3e4bf0d, f5ec35a
Parents:
790d835
Message:

Remove BaseSyntaxNode? and clean-up.

Location:
src/Tuples
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/Explode.cc

    r790d835 rc6b4432  
    1515
    1616#include "Explode.h"
    17 #include <list>                  // for list
    1817
    1918#include "AST/Pass.hpp"          // for Pass
    20 #include "SynTree/Mutator.h"     // for Mutator
    21 #include "Common/PassVisitor.h"  // for PassVisitor
    2219
    2320namespace Tuples {
    24         namespace {
    25                 // remove one level of reference from a reference type -- may be useful elsewhere.
    26                 Type * getReferenceBase( Type * t ) {
    27                         if ( ReferenceType * refType = dynamic_cast<ReferenceType *>( t ) ) {
    28                                 return refType->get_base();
    29                         } else {
    30                                 // for the moment, I want to know immediately if a non-reference type is ever passed in here.
    31                                 assertf( false, "getReferenceBase for non-ref: %s", toString( refType ).c_str() );
    32                                 return nullptr;
    33                         }
    34                 }
    35 
    36                 struct CastExploder {
    37                         bool castAdded = false;
    38                         bool foundUniqueExpr = false;
    39                         Expression * applyCast( Expression * expr, bool first = true ) {
    40                                 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){
    41                                         foundUniqueExpr = true;
    42                                         std::list< Expression * > exprs;
    43                                         for ( Expression *& expr : tupleExpr->get_exprs() ) {
    44                                                 // move cast into tuple exprs
    45                                                 exprs.push_back( applyCast( expr, false ) );
    46                                         }
    47                                         // want the top-level expression to be cast to reference type, but not nested
    48                                         // tuple expressions
    49                                         if ( first ) {
    50                                                 castAdded = true;
    51                                                 Expression * tupleExpr = new TupleExpr( exprs );
    52                                                 return new CastExpr( tupleExpr, new ReferenceType( Type::Qualifiers(), tupleExpr->result->clone() ) );
    53                                         } else {
    54                                                 return new TupleExpr( exprs );
    55                                         }
    56                                 }
    57                                 if ( dynamic_cast<ReferenceType*>( expr->result ) ) {
    58                                         // don't need to cast reference type to another reference type
    59                                         return expr->clone();
    60                                 } else {
    61                                         // anything else should be cast to reference as normal
    62                                         castAdded = true;
    63                                         return new CastExpr( expr->clone(), new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
    64                                 }
    65                         }
    66 
    67                         Expression * postmutate( UniqueExpr * uniqueExpr ) {
    68                                 // move cast into unique expr so that the unique expr has type T& rather than
    69                                 // type T. In particular, this transformation helps with generating the
    70                                 // correct code for reference-cast member tuple expressions, since the result
    71                                 // should now be a tuple of references rather than a reference to a tuple.
    72                                 // Still, this code is a bit awkward, and could use some improvement.
    73                                 UniqueExpr * newUniqueExpr = new UniqueExpr( applyCast( uniqueExpr->get_expr() ), uniqueExpr->get_id() );
    74                                 delete uniqueExpr;
    75                                 if ( castAdded ) {
    76                                         // if a cast was added by applyCast, then unique expr now has one more layer of reference
    77                                         // than it had coming into this function. To ensure types still match correctly, need to cast
    78                                         //  to reference base so that outer expressions are still correct.
    79                                         castAdded = false;
    80                                         Type * toType = getReferenceBase( newUniqueExpr->result );
    81                                         return new CastExpr( newUniqueExpr, toType->clone() );
    82                                 }
    83                                 return newUniqueExpr;
    84                         }
    85 
    86 
    87                         Expression * postmutate( TupleIndexExpr * tupleExpr ) {
    88                                 // tuple index expr needs to be rebuilt to ensure that the type of the
    89                                 // field is consistent with the type of the tuple expr, since the field
    90                                 // may have changed from type T to T&.
    91                                 Expression * expr = tupleExpr->get_tuple();
    92                                 tupleExpr->set_tuple( nullptr );
    93                                 TupleIndexExpr * ret = new TupleIndexExpr( expr, tupleExpr->get_index() );
    94                                 delete tupleExpr;
    95                                 return ret;
    96                         }
    97                 };
    98         } // namespace
    99 
    100         Expression * distributeReference( Expression * expr ) {
    101                 PassVisitor<CastExploder> exploder;
    102                 expr = expr->acceptMutator( exploder );
    103                 if ( ! exploder.pass.foundUniqueExpr ) {
    104                         // if a UniqueExpr was found, then the cast has already been added inside the UniqueExpr as appropriate
    105                         expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
    106                 }
    107                 return expr;
    108         }
    10921
    11022namespace {
  • src/Tuples/Explode.h

    r790d835 rc6b4432  
    2020
    2121#include "AST/Expr.hpp"
    22 #include "ResolvExpr/Alternative.h"     // for Alternative, AltList
    2322#include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
    24 #include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
    2523#include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
    26 #include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
    27 #include "SynTree/Type.h"               // for TupleType, Type
    2824#include "Tuples.h"                     // for maybeImpure
    2925
     
    3228}
    3329
    34 namespace SymTab {
    35 class Indexer;
    36 }  // namespace SymTab
    37 
    3830namespace 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         }
    13931
    14032const ast::Expr * distributeReference( const ast::Expr * );
  • src/Tuples/TupleAssignment.cc

    r790d835 rc6b4432  
    2828#include "AST/TypeEnvironment.hpp"
    2929#include "CodeGen/OperatorTable.h"
    30 #include "Common/PassVisitor.h"
    3130#include "Common/UniqueName.h"             // for UniqueName
    3231#include "Common/utility.h"                // for splice, zipWith
     
    3433#include "InitTweak/GenInit.h"             // for genCtorInit
    3534#include "InitTweak/InitTweak.h"           // for getPointerBase, isAssignment
    36 #include "ResolvExpr/Alternative.h"        // for AltList, Alternative
    37 #include "ResolvExpr/AlternativeFinder.h"  // for AlternativeFinder, simpleC...
    3835#include "ResolvExpr/Cost.h"               // for Cost
    3936#include "ResolvExpr/Resolver.h"           // for resolveCtorInit
    40 #include "ResolvExpr/TypeEnvironment.h"    // for TypeEnvironment
    4137#include "ResolvExpr/typeops.h"            // for combos
    42 #include "SynTree/LinkageSpec.h"           // for Cforall
    43 #include "SynTree/Declaration.h"           // for ObjectDecl
    44 #include "SynTree/Expression.h"            // for Expression, CastExpr, Name...
    45 #include "SynTree/Initializer.h"           // for ConstructorInit, SingleInit
    46 #include "SynTree/Statement.h"             // for ExprStmt
    47 #include "SynTree/Type.h"                  // for Type, Type::Qualifiers
    48 #include "SynTree/TypeSubstitution.h"      // for TypeSubstitution
    49 #include "SynTree/Visitor.h"               // for Visitor
    5038
    5139#if 0
     
    5644
    5745namespace Tuples {
    58         class TupleAssignSpotter_old {
    59           public:
    60                 // dispatcher for Tuple (multiple and mass) assignment operations
    61                 TupleAssignSpotter_old( ResolvExpr::AlternativeFinder & );
    62                 void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args );
    63 
    64           private:
    65                 void match();
    66 
    67                 struct Matcher {
    68                   public:
    69                         Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    70                                 const ResolvExpr::AltList& rhs );
    71                         virtual ~Matcher() {}
    72 
    73                         virtual void match( std::list< Expression * > &out ) = 0;
    74                         ObjectDecl * newObject( UniqueName & namer, Expression * expr );
    75 
    76                         void combineState( const ResolvExpr::Alternative& alt ) {
    77                                 compositeEnv.simpleCombine( alt.env );
    78                                 ResolvExpr::mergeOpenVars( openVars, alt.openVars );
    79                                 cloneAll( alt.need, need );
    80                         }
    81 
    82                         void combineState( const ResolvExpr::AltList& alts ) {
    83                                 for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); }
    84                         }
    85 
    86                         ResolvExpr::AltList lhs, rhs;
    87                         TupleAssignSpotter_old &spotter;
    88                         ResolvExpr::Cost baseCost;
    89                         std::list< ObjectDecl * > tmpDecls;
    90                         ResolvExpr::TypeEnvironment compositeEnv;
    91                         ResolvExpr::OpenVarSet openVars;
    92                         ResolvExpr::AssertionSet need;
    93                 };
    94 
    95                 struct MassAssignMatcher : public Matcher {
    96                   public:
    97                         MassAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    98                                 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    99                         virtual void match( std::list< Expression * > &out );
    100                 };
    101 
    102                 struct MultipleAssignMatcher : public Matcher {
    103                   public:
    104                         MultipleAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    105                                 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    106                         virtual void match( std::list< Expression * > &out );
    107                 };
    108 
    109                 ResolvExpr::AlternativeFinder &currentFinder;
    110                 std::string fname;
    111                 std::unique_ptr< Matcher > matcher;
    112         };
    113 
    114         /// true if expr is an expression of tuple type
    115         bool isTuple( Expression *expr ) {
    116                 if ( ! expr ) return false;
    117                 assert( expr->result );
    118                 return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
    119         }
    120 
    121         template< typename AltIter >
    122         bool isMultAssign( AltIter begin, AltIter end ) {
    123                 // multiple assignment if more than one alternative in the range or if
    124                 // the alternative is a tuple
    125                 if ( begin == end ) return false;
    126                 if ( isTuple( begin->expr ) ) return true;
    127                 return ++begin != end;
    128         }
    129 
    130         bool refToTuple( Expression *expr ) {
    131                 assert( expr->get_result() );
    132                 // also check for function returning tuple of reference types
    133                 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    134                         return refToTuple( castExpr->get_arg() );
    135                 } else {
    136                         return isTuple( expr );
    137                 }
    138                 return false;
    139         }
    140 
    141         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
    142                                 std::vector<ResolvExpr::AlternativeFinder> &args ) {
    143                 TupleAssignSpotter_old spotter( currentFinder );
    144                 spotter.spot( expr, args );
    145         }
    146 
    147         TupleAssignSpotter_old::TupleAssignSpotter_old( ResolvExpr::AlternativeFinder &f )
    148                 : currentFinder(f) {}
    149 
    150         void TupleAssignSpotter_old::spot( UntypedExpr * expr,
    151                         std::vector<ResolvExpr::AlternativeFinder> &args ) {
    152                 if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    153                         if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
    154                                 fname = op->get_name();
    155 
    156                                 // AlternativeFinder will naturally handle this case case, if it's legal
    157                                 if ( args.size() == 0 ) return;
    158 
    159                                 // if an assignment only takes 1 argument, that's odd, but maybe someone wrote
    160                                 // the function, in which case AlternativeFinder will handle it normally
    161                                 if ( args.size() == 1 && CodeGen::isAssignment( fname ) ) return;
    162 
    163                                 // look over all possible left-hand-sides
    164                                 for ( ResolvExpr::Alternative& lhsAlt : args[0] ) {
    165                                         // skip non-tuple LHS
    166                                         if ( ! refToTuple(lhsAlt.expr) ) continue;
    167 
    168                                         // explode is aware of casts - ensure every LHS expression is sent into explode
    169                                         // with a reference cast
    170                                         // xxx - this seems to change the alternatives before the normal
    171                                         //  AlternativeFinder flow; maybe this is desired?
    172                                         if ( ! dynamic_cast<CastExpr*>( lhsAlt.expr ) ) {
    173                                                 lhsAlt.expr = new CastExpr( lhsAlt.expr,
    174                                                                 new ReferenceType( Type::Qualifiers(),
    175                                                                         lhsAlt.expr->result->clone() ) );
    176                                         }
    177 
    178                                         // explode the LHS so that each field of a tuple-valued-expr is assigned
    179                                         ResolvExpr::AltList lhs;
    180                                         explode( lhsAlt, currentFinder.get_indexer(), back_inserter(lhs), true );
    181                                         for ( ResolvExpr::Alternative& alt : lhs ) {
    182                                                 // each LHS value must be a reference - some come in with a cast expression,
    183                                                 // if not just cast to reference here
    184                                                 if ( ! dynamic_cast<ReferenceType*>( alt.expr->get_result() ) ) {
    185                                                         alt.expr = new CastExpr( alt.expr,
    186                                                                 new ReferenceType( Type::Qualifiers(),
    187                                                                         alt.expr->get_result()->clone() ) );
    188                                                 }
    189                                         }
    190 
    191                                         if ( args.size() == 1 ) {
    192                                                 // mass default-initialization/destruction
    193                                                 ResolvExpr::AltList rhs{};
    194                                                 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
    195                                                 match();
    196                                         } else if ( args.size() > 2 ) {
    197                                                 // expand all possible RHS possibilities
    198                                                 // TODO build iterative version of this instead of using combos
    199                                                 std::vector< ResolvExpr::AltList > rhsAlts;
    200                                                 combos( std::next(args.begin(), 1), args.end(),
    201                                                         std::back_inserter( rhsAlts ) );
    202                                                 for ( const ResolvExpr::AltList& rhsAlt : rhsAlts ) {
    203                                                         // multiple assignment
    204                                                         ResolvExpr::AltList rhs;
    205                                                         explode( rhsAlt, currentFinder.get_indexer(),
    206                                                                 std::back_inserter(rhs), true );
    207                                                         matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
    208                                                         match();
    209                                                 }
    210                                         } else {
    211                                                 for ( const ResolvExpr::Alternative& rhsAlt : args[1] ) {
    212                                                         ResolvExpr::AltList rhs;
    213                                                         if ( isTuple(rhsAlt.expr) ) {
    214                                                                 // multiple assignment
    215                                                                 explode( rhsAlt, currentFinder.get_indexer(),
    216                                                                         std::back_inserter(rhs), true );
    217                                                                 matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
    218                                                         } else {
    219                                                                 // mass assignment
    220                                                                 rhs.push_back( rhsAlt );
    221                                                                 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
    222                                                         }
    223                                                         match();
    224                                                 }
    225                                         }
    226                                 }
    227                         }
    228                 }
    229         }
    230 
    231         void TupleAssignSpotter_old::match() {
    232                 assert ( matcher != 0 );
    233 
    234                 std::list< Expression * > new_assigns;
    235                 matcher->match( new_assigns );
    236 
    237                 if ( ! matcher->lhs.empty() || ! matcher->rhs.empty() ) {
    238                         // if both lhs and rhs are empty then this is the empty tuple case, wherein it's okay for new_assigns to be empty.
    239                         // if not the empty tuple case, return early so that no new alternatives are generated.
    240                         if ( new_assigns.empty() ) return;
    241                 }
    242                 ResolvExpr::AltList current;
    243                 // now resolve new assignments
    244                 for ( std::list< Expression * >::iterator i = new_assigns.begin();
    245                                 i != new_assigns.end(); ++i ) {
    246                         PRINT(
    247                                 std::cerr << "== resolving tuple assign ==" << std::endl;
    248                                 std::cerr << *i << std::endl;
    249                         )
    250 
    251                         ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(),
    252                                 matcher->compositeEnv };
    253 
    254                         try {
    255                                 finder.findWithAdjustment(*i);
    256                         } catch (...) {
    257                                 return; // no match should not mean failure, it just means this particular tuple assignment isn't valid
    258                         }
    259                         // prune expressions that don't coincide with
    260                         ResolvExpr::AltList alts = finder.get_alternatives();
    261                         assert( alts.size() == 1 );
    262                         assert( alts.front().expr != 0 );
    263                         current.push_back( alts.front() );
    264                 }
    265 
    266                 // extract expressions from the assignment alternatives to produce a list of assignments
    267                 // that together form a single alternative
    268                 std::list< Expression *> solved_assigns;
    269                 for ( ResolvExpr::Alternative & alt : current ) {
    270                         solved_assigns.push_back( alt.expr->clone() );
    271                         matcher->combineState( alt );
    272                 }
    273 
    274                 // xxx -- was push_front
    275                 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{
    276                         new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv,
    277                         matcher->openVars,
    278                         ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ),
    279                         ResolvExpr::sumCost( current ) + matcher->baseCost } );
    280         }
    281 
    282         TupleAssignSpotter_old::Matcher::Matcher( TupleAssignSpotter_old &spotter,
    283                 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs )
    284         : lhs(lhs), rhs(rhs), spotter(spotter),
    285           baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
    286                 combineState( lhs );
    287                 combineState( rhs );
    288         }
    289 
    290         UntypedExpr * createFunc( const std::string &fname, ObjectDecl *left, ObjectDecl *right ) {
    291                 assert( left );
    292                 std::list< Expression * > args;
    293                 args.push_back( new VariableExpr( left ) );
    294                 // args.push_back( new AddressExpr( new VariableExpr( left ) ) );
    295                 if ( right ) args.push_back( new VariableExpr( right ) );
    296                 if ( left->type->referenceDepth() > 1 && CodeGen::isConstructor( fname ) ) {
    297                         args.front() = new AddressExpr( args.front() );
    298                         if ( right ) args.back() = new AddressExpr( args.back() );
    299                         return new UntypedExpr( new NameExpr( "?=?" ), args );
    300                 } else {
    301                         return new UntypedExpr( new NameExpr( fname ), args );
    302                 }
    303         }
    304 
    305         // removes environments from subexpressions within statement exprs, which could throw off later passes like those in Box which rely on PolyMutator, and adds the bindings to the compositeEnv
    306         // xxx - maybe this should happen in alternative finder for every StmtExpr?
    307         struct EnvRemover {
    308                 void previsit( ExprStmt * stmt ) {
    309                         assert( compositeEnv );
    310                         if ( stmt->expr->env ) {
    311                                 compositeEnv->add( *stmt->expr->env );
    312                                 delete stmt->expr->env;
    313                                 stmt->expr->env = nullptr;
    314                         }
    315                 }
    316 
    317                 ResolvExpr::TypeEnvironment * compositeEnv = nullptr;
    318         };
    319 
    320         ObjectDecl * TupleAssignSpotter_old::Matcher::newObject( UniqueName & namer, Expression * expr ) {
    321                 assert( expr->result && ! expr->get_result()->isVoid() );
    322                 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->result->clone(), new SingleInit( expr->clone() ) );
    323                 // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
    324                 if ( ! dynamic_cast< ReferenceType * >( expr->result ) ) {
    325                         ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
    326                         ret->init = ctorInit;
    327                         ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
    328                         PassVisitor<EnvRemover> rm; // remove environments from subexpressions of StmtExprs
    329                         rm.pass.compositeEnv = &compositeEnv;
    330                         ctorInit->accept( rm );
    331                 }
    332                 PRINT( std::cerr << "new object: " << ret << std::endl; )
    333                 return ret;
    334         }
    335 
    336         void TupleAssignSpotter_old::MassAssignMatcher::match( std::list< Expression * > &out ) {
    337                 static UniqueName lhsNamer( "__massassign_L" );
    338                 static UniqueName rhsNamer( "__massassign_R" );
    339                 // empty tuple case falls into this matcher, hence the second part of the assert
    340                 assert( (! lhs.empty() && rhs.size() <= 1) || (lhs.empty() && rhs.empty()) );
    341 
    342                 // xxx - may need to split this up into multiple declarations, because potential conversion to references
    343                 //  probably should not reference local variable - see MultipleAssignMatcher::match
    344                 ObjectDecl * rtmp = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr;
    345                 for ( ResolvExpr::Alternative & lhsAlt : lhs ) {
    346                         // create a temporary object for each value in the lhs and create a call involving the rhs
    347                         ObjectDecl * ltmp = newObject( lhsNamer, lhsAlt.expr );
    348                         out.push_back( createFunc( spotter.fname, ltmp, rtmp ) );
    349                         tmpDecls.push_back( ltmp );
    350                 }
    351                 if ( rtmp ) tmpDecls.push_back( rtmp );
    352         }
    353 
    354         void TupleAssignSpotter_old::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
    355                 static UniqueName lhsNamer( "__multassign_L" );
    356                 static UniqueName rhsNamer( "__multassign_R" );
    357 
    358                 if ( lhs.size() == rhs.size() ) {
    359                         // produce a new temporary object for each value in the lhs and rhs and pairwise create the calls
    360                         std::list< ObjectDecl * > ltmp;
    361                         std::list< ObjectDecl * > rtmp;
    362                         for ( auto p : group_iterate( lhs, rhs ) ) {
    363                                 ResolvExpr::Alternative & lhsAlt = std::get<0>(p);
    364                                 ResolvExpr::Alternative & rhsAlt = std::get<1>(p);
    365                                 // convert RHS to LHS type minus one reference -- important for the case where LHS is && and RHS is lvalue, etc.
    366                                 ReferenceType * lhsType = strict_dynamic_cast<ReferenceType *>( lhsAlt.expr->result );
    367                                 rhsAlt.expr = new CastExpr( rhsAlt.expr, lhsType->base->clone() );
    368                                 ObjectDecl * lobj = newObject( lhsNamer, lhsAlt.expr );
    369                                 ObjectDecl * robj = newObject( rhsNamer, rhsAlt.expr );
    370                                 out.push_back( createFunc(spotter.fname, lobj, robj) );
    371                                 ltmp.push_back( lobj );
    372                                 rtmp.push_back( robj );
    373 
    374                                 // resolve the cast expression so that rhsAlt return type is bound by the cast type as needed, and transfer the resulting environment
    375                                 ResolvExpr::AlternativeFinder finder{ spotter.currentFinder.get_indexer(), compositeEnv };
    376                                 finder.findWithAdjustment( rhsAlt.expr );
    377                                 assert( finder.get_alternatives().size() == 1 );
    378                                 compositeEnv = std::move( finder.get_alternatives().front().env );
    379                         }
    380                         tmpDecls.splice( tmpDecls.end(), ltmp );
    381                         tmpDecls.splice( tmpDecls.end(), rtmp );
    382                 }
    383         }
    38446
    38547namespace {
  • src/Tuples/TupleExpansion.cc

    r790d835 rc6b4432  
    2323#include "AST/Node.hpp"
    2424#include "AST/Type.hpp"
    25 #include "Common/PassVisitor.h"   // for PassVisitor, WithDeclsToAdd, WithGu...
    2625#include "Common/ScopedMap.h"     // for ScopedMap
    2726#include "Common/utility.h"       // for CodeLocation
    2827#include "InitTweak/InitTweak.h"  // for getFunction
    29 #include "SynTree/LinkageSpec.h"  // for Spec, C, Intrinsic
    30 #include "SynTree/Constant.h"     // for Constant
    31 #include "SynTree/Declaration.h"  // for StructDecl, DeclarationWithType
    32 #include "SynTree/Expression.h"   // for UntypedMemberExpr, Expression, Uniq...
    33 #include "SynTree/Label.h"        // for operator==, Label
    34 #include "SynTree/Mutator.h"      // for Mutator
    35 #include "SynTree/Type.h"         // for Type, Type::Qualifiers, TupleType
    36 #include "SynTree/Visitor.h"      // for Visitor
    3728#include "Tuples.h"
    3829
    39 class CompoundStmt;
    40 class TypeSubstitution;
     30namespace Tuples {
    4131
    42 namespace Tuples {
    43         namespace {
    44                 struct MemberTupleExpander final : public WithShortCircuiting, public WithVisitorRef<MemberTupleExpander> {
    45                         void premutate( UntypedMemberExpr * ) { visit_children = false; }
    46                         Expression * postmutate( UntypedMemberExpr * memberExpr );
    47                 };
    48 
    49                 struct UniqueExprExpander final : public WithDeclsToAdd {
    50                         Expression * postmutate( UniqueExpr * unqExpr );
    51 
    52                         std::map< int, Expression * > decls; // not vector, because order added may not be increasing order
    53 
    54                         ~UniqueExprExpander() {
    55                                 for ( std::pair<const int, Expression *> & p : decls ) {
    56                                         delete p.second;
    57                                 }
    58                         }
    59                 };
    60 
    61                 struct TupleAssignExpander {
    62                         Expression * postmutate( TupleAssignExpr * tupleExpr );
    63                 };
    64 
    65                 struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithConstTypeSubstitution {
    66                         Type * postmutate( TupleType * tupleType );
    67 
    68                         void premutate( CompoundStmt * ) {
    69                                 GuardScope( typeMap );
    70                         }
    71                   private:
    72                         ScopedMap< int, StructDecl * > typeMap;
    73                 };
    74 
    75                 struct TupleIndexExpander {
    76                         Expression * postmutate( TupleIndexExpr * tupleExpr );
    77                 };
    78 
    79                 struct TupleExprExpander final {
    80                         Expression * postmutate( TupleExpr * tupleExpr );
    81                 };
    82         }
    83 
    84         void expandMemberTuples( std::list< Declaration * > & translationUnit ) {
    85                 PassVisitor<MemberTupleExpander> expander;
    86                 mutateAll( translationUnit, expander );
    87         }
    88 
    89         void expandUniqueExpr( std::list< Declaration * > & translationUnit ) {
    90                 PassVisitor<UniqueExprExpander> unqExpander;
    91                 mutateAll( translationUnit, unqExpander );
    92         }
    93 
    94         void expandTuples( std::list< Declaration * > & translationUnit ) {
    95                 PassVisitor<TupleAssignExpander> assnExpander;
    96                 mutateAll( translationUnit, assnExpander );
    97 
    98                 PassVisitor<TupleTypeReplacer> replacer;
    99                 mutateAll( translationUnit, replacer );
    100 
    101                 PassVisitor<TupleIndexExpander> idxExpander;
    102                 mutateAll( translationUnit, idxExpander );
    103 
    104                 PassVisitor<TupleExprExpander> exprExpander;
    105                 mutateAll( translationUnit, exprExpander );
    106         }
    107 
    108         namespace {
    109                 /// given a expression representing the member and an expression representing the aggregate,
    110                 /// reconstructs a flattened UntypedMemberExpr with the right precedence
    111                 Expression * reconstructMemberExpr( Expression * member, Expression * aggr, CodeLocation & loc ) {
    112                         if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( member ) ) {
    113                                 // construct a new UntypedMemberExpr with the correct structure , and recursively
    114                                 // expand that member expression.
    115                                 PassVisitor<MemberTupleExpander> expander;
    116                                 UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr->aggregate, aggr->clone() );
    117                                 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member, inner );
    118                                 inner->location = newMemberExpr->location = loc;
    119                                 memberExpr->member = nullptr;
    120                                 memberExpr->aggregate = nullptr;
    121                                 delete memberExpr;
    122                                 return newMemberExpr->acceptMutator( expander );
    123                         } else {
    124                                 // not a member expression, so there is nothing to do but attach and return
    125                                 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( member, aggr->clone() );
    126                                 newMemberExpr->location = loc;
    127                                 return newMemberExpr;
    128                         }
    129                 }
    130         }
    131 
    132         Expression * MemberTupleExpander::postmutate( UntypedMemberExpr * memberExpr ) {
    133                 if ( UntypedTupleExpr * tupleExpr = dynamic_cast< UntypedTupleExpr * > ( memberExpr->member ) ) {
    134                         Expression * aggr = memberExpr->aggregate->clone()->acceptMutator( *visitor );
    135                         // aggregate expressions which might be impure must be wrapped in unique expressions
    136                         if ( Tuples::maybeImpureIgnoreUnique( memberExpr->aggregate ) ) aggr = new UniqueExpr( aggr );
    137                         for ( Expression *& expr : tupleExpr->exprs ) {
    138                                 expr = reconstructMemberExpr( expr, aggr, memberExpr->location );
    139                                 expr->location = memberExpr->location;
    140                         }
    141                         delete aggr;
    142                         tupleExpr->location = memberExpr->location;
    143                         return tupleExpr;
    144                 } else {
    145                         // there may be a tuple expr buried in the aggregate
    146                         // xxx - this is a memory leak
    147                         UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member->clone(), memberExpr->aggregate->acceptMutator( *visitor ) );
    148                         newMemberExpr->location = memberExpr->location;
    149                         return newMemberExpr;
    150                 }
    151         }
    152 
    153         Expression * UniqueExprExpander::postmutate( UniqueExpr * unqExpr ) {
    154                 const int id = unqExpr->get_id();
    155 
    156                 // on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID,
    157                 // and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable.
    158                 if ( ! decls.count( id ) ) {
    159                         Expression * assignUnq;
    160                         Expression * var = unqExpr->get_var();
    161                         if ( unqExpr->get_object() ) {
    162                                 // an object was generated to represent this unique expression -- it should be added to the list of declarations now
    163                                 declsToAddBefore.push_back( unqExpr->get_object() );
    164                                 unqExpr->set_object( nullptr );
    165                                 // steal the expr from the unqExpr
    166                                 assignUnq = UntypedExpr::createAssign( unqExpr->get_var()->clone(), unqExpr->get_expr() );
    167                                 unqExpr->set_expr( nullptr );
    168                         } else {
    169                                 // steal the already generated assignment to var from the unqExpr - this has been generated by FixInit
    170                                 Expression * expr = unqExpr->get_expr();
    171                                 CommaExpr * commaExpr = strict_dynamic_cast< CommaExpr * >( expr );
    172                                 assignUnq = commaExpr->get_arg1();
    173                                 commaExpr->set_arg1( nullptr );
    174                         }
    175                         ObjectDecl * finished = new ObjectDecl( toString( "_unq", id, "_finished_" ), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ),
    176                                                                                                         new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) );
    177                         declsToAddBefore.push_back( finished );
    178                         // (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
    179                         // This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code.
    180                         Expression * assignFinished = UntypedExpr::createAssign( new VariableExpr(finished), new ConstantExpr( Constant::from_int( 1 ) ) );
    181                         ConditionalExpr * condExpr = new ConditionalExpr( new VariableExpr( finished ), var->clone(),
    182                                 new CommaExpr( new CommaExpr( assignUnq, assignFinished ), var->clone() ) );
    183                         condExpr->set_result( var->get_result()->clone() );
    184                         condExpr->set_env( maybeClone( unqExpr->get_env() ) );
    185                         decls[id] = condExpr;
    186                 }
    187                 delete unqExpr;
    188                 return decls[id]->clone();
    189         }
    190 
    191         Expression * TupleAssignExpander::postmutate( TupleAssignExpr * assnExpr ) {
    192                 StmtExpr * ret = assnExpr->get_stmtExpr();
    193                 assnExpr->set_stmtExpr( nullptr );
    194                 // move env to StmtExpr
    195                 ret->set_env( assnExpr->get_env() );
    196                 assnExpr->set_env( nullptr );
    197                 delete assnExpr;
    198                 return ret;
    199         }
    200 
    201         Type * TupleTypeReplacer::postmutate( TupleType * tupleType ) {
    202                 unsigned tupleSize = tupleType->size();
    203                 if ( ! typeMap.count( tupleSize ) ) {
    204                         // generate struct type to replace tuple type based on the number of components in the tuple
    205                         StructDecl * decl = new StructDecl( toString( "_tuple", tupleSize, "_" ) );
    206                         decl->location = tupleType->location;
    207                         decl->set_body( true );
    208                         for ( size_t i = 0; i < tupleSize; ++i ) {
    209                                 TypeDecl * tyParam = new TypeDecl( toString( "tuple_param_", tupleSize, "_", i ), Type::StorageClasses(), nullptr, TypeDecl::Dtype, true );
    210                                 decl->get_members().push_back( new ObjectDecl( toString("field_", i ), Type::StorageClasses(), LinkageSpec::C, nullptr, new TypeInstType( Type::Qualifiers(), tyParam->get_name(), tyParam ), nullptr ) );
    211                                 decl->get_parameters().push_back( tyParam );
    212                         }
    213                         if ( tupleSize == 0 ) {
    214                                 // empty structs are not standard C. Add a dummy field to empty tuples to silence warnings when a compound literal Tuple0 is created.
    215                                 decl->get_members().push_back( new ObjectDecl( "dummy", Type::StorageClasses(), LinkageSpec::C, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) );
    216                         }
    217                         typeMap[tupleSize] = decl;
    218                         declsToAddBefore.push_back( decl );
    219                 }
    220                 Type::Qualifiers qualifiers = tupleType->get_qualifiers();
    221 
    222                 StructDecl * decl = typeMap[tupleSize];
    223                 StructInstType * newType = new StructInstType( qualifiers, decl );
    224                 for ( auto p : group_iterate( tupleType->get_types(), decl->get_parameters() ) ) {
    225                         Type * t = std::get<0>(p);
    226                         newType->get_parameters().push_back( new TypeExpr( t->clone() ) );
    227                 }
    228                 delete tupleType;
    229                 return newType;
    230         }
    231 
    232         Expression * TupleIndexExpander::postmutate( TupleIndexExpr * tupleExpr ) {
    233                 Expression * tuple = tupleExpr->tuple;
    234                 assert( tuple );
    235                 tupleExpr->tuple = nullptr;
    236                 unsigned int idx = tupleExpr->index;
    237                 TypeSubstitution * env = tupleExpr->env;
    238                 tupleExpr->env = nullptr;
    239                 delete tupleExpr;
    240 
    241                 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * > ( tuple ) ) {
    242                         if ( ! maybeImpureIgnoreUnique( tupleExpr ) ) {
    243                                 // optimization: definitely pure tuple expr => can reduce to the only relevant component.
    244                                 assert( tupleExpr->exprs.size() > idx );
    245                                 Expression *& expr = *std::next(tupleExpr->exprs.begin(), idx);
    246                                 Expression * ret = expr;
    247                                 ret->env = env;
    248                                 expr = nullptr; // remove from list so it can safely be deleted
    249                                 delete tupleExpr;
    250                                 return ret;
    251                         }
    252                 }
    253 
    254                 StructInstType * type = strict_dynamic_cast< StructInstType * >( tuple->result );
    255                 StructDecl * structDecl = type->baseStruct;
    256                 assert( structDecl->members.size() > idx );
    257                 Declaration * member = *std::next(structDecl->members.begin(), idx);
    258                 MemberExpr * memExpr = new MemberExpr( strict_dynamic_cast< DeclarationWithType * >( member ), tuple );
    259                 memExpr->env = env;
    260                 return memExpr;
    261         }
    262 
    263         Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs, TypeSubstitution * env ) {
    264                 if ( result->isVoid() ) {
    265                         // void result - don't need to produce a value for cascading - just output a chain of comma exprs
    266                         assert( ! exprs.empty() );
    267                         std::list< Expression * >::const_iterator iter = exprs.begin();
    268                         Expression * expr = new CastExpr( *iter++ );
    269                         for ( ; iter != exprs.end(); ++iter ) {
    270                                 expr = new CommaExpr( expr, new CastExpr( *iter ) );
    271                         }
    272                         expr->set_env( env );
    273                         return expr;
    274                 } else {
    275                         // typed tuple expression - produce a compound literal which performs each of the expressions
    276                         // as a distinct part of its initializer - the produced compound literal may be used as part of
    277                         // another expression
    278                         std::list< Initializer * > inits;
    279                         for ( Expression * expr : exprs ) {
    280                                 inits.push_back( new SingleInit( expr ) );
    281                         }
    282                         Expression * expr = new CompoundLiteralExpr( result, new ListInit( inits ) );
    283                         expr->set_env( env );
    284                         return expr;
    285                 }
    286         }
    287 
    288         Expression * TupleExprExpander::postmutate( TupleExpr * tupleExpr ) {
    289                 Type * result = tupleExpr->get_result();
    290                 std::list< Expression * > exprs = tupleExpr->get_exprs();
    291                 assert( result );
    292                 TypeSubstitution * env = tupleExpr->get_env();
    293 
    294                 // remove data from shell and delete it
    295                 tupleExpr->set_result( nullptr );
    296                 tupleExpr->get_exprs().clear();
    297                 tupleExpr->set_env( nullptr );
    298                 delete tupleExpr;
    299 
    300                 return replaceTupleExpr( result, exprs, env );
    301         }
    302 
    303         Type * makeTupleType( const std::list< Expression * > & exprs ) {
    304                 // produce the TupleType which aggregates the types of the exprs
    305                 std::list< Type * > types;
    306                 Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic | Type::Mutex );
    307                 for ( Expression * expr : exprs ) {
    308                         assert( expr->get_result() );
    309                         if ( expr->get_result()->isVoid() ) {
    310                                 // if the type of any expr is void, the type of the entire tuple is void
    311                                 return new VoidType( Type::Qualifiers() );
    312                         }
    313                         Type * type = expr->get_result()->clone();
    314                         types.push_back( type );
    315                         // the qualifiers on the tuple type are the qualifiers that exist on all component types
    316                         qualifiers &= type->get_qualifiers();
    317                 } // for
    318                 if ( exprs.empty() ) qualifiers = Type::Qualifiers();
    319                 return new TupleType( qualifiers, types );
    320         }
    32132        const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs ) {
    32233                // produce the TupleType which aggregates the types of the exprs
     
    34152        }
    34253
    343         TypeInstType * isTtype( Type * type ) {
    344                 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( type ) ) {
    345                         if ( inst->get_baseType() && inst->get_baseType()->get_kind() == TypeDecl::Ttype ) {
    346                                 return inst;
    347                         }
    348                 }
    349                 return nullptr;
    350         }
    351 
    352         const TypeInstType * isTtype( const Type * type ) {
    353                 if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type ) ) {
    354                         if ( inst->baseType && inst->baseType->kind == TypeDecl::Ttype ) {
    355                                 return inst;
    356                         }
    357                 }
    358                 return nullptr;
    359         }
    360 
    36154        const ast::TypeInstType * isTtype( const ast::Type * type ) {
    36255                if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
  • src/Tuples/Tuples.cc

    r790d835 rc6b4432  
    1919#include "AST/Inspect.hpp"
    2020#include "AST/LinkageSpec.hpp"
    21 #include "Common/PassVisitor.h"
    2221#include "InitTweak/InitTweak.h"
    2322
     
    2524
    2625namespace {
    27         /// Checks if impurity (read: side-effects) may exist in a piece of code.
    28         /// Currently gives a very crude approximation, wherein any function
    29         /// call expression means the code may be impure.
    30         struct ImpurityDetector_old : public WithShortCircuiting {
    31                 bool const ignoreUnique;
    32                 bool maybeImpure;
    33 
    34                 ImpurityDetector_old( bool ignoreUnique ) :
    35                         ignoreUnique( ignoreUnique ), maybeImpure( false )
    36                 {}
    37 
    38                 void previsit( const ApplicationExpr * appExpr ) {
    39                         visit_children = false;
    40                         if ( const DeclarationWithType * function =
    41                                         InitTweak::getFunction( appExpr ) ) {
    42                                 if ( function->linkage == LinkageSpec::Intrinsic ) {
    43                                         if ( function->name == "*?" || function->name == "?[?]" ) {
    44                                                 // intrinsic dereference, subscript are pure,
    45                                                 // but need to recursively look for impurity
    46                                                 visit_children = true;
    47                                                 return;
    48                                         }
    49                                 }
    50                         }
    51                         maybeImpure = true;
    52                 }
    53 
    54                 void previsit( const UntypedExpr * ) {
    55                         maybeImpure = true;
    56                         visit_children = false;
    57                 }
    58 
    59                 void previsit( const UniqueExpr * ) {
    60                         if ( ignoreUnique ) {
    61                                 // bottom out at unique expression.
    62                                 // The existence of a unique expression doesn't change the purity of an expression.
    63                                 // That is, even if the wrapped expression is impure, the wrapper protects the rest of the expression.
    64                                 visit_children = false;
    65                                 return;
    66                         }
    67                 }
    68         };
    69 
    70         bool detectImpurity( const Expression * expr, bool ignoreUnique ) {
    71                 PassVisitor<ImpurityDetector_old> detector( ignoreUnique );
    72                 expr->accept( detector );
    73                 return detector.pass.maybeImpure;
    74         }
    7526
    7627        /// Determines if impurity (read: side-effects) may exist in a piece of code. Currently gives
     
    11061}
    11162
    112 bool maybeImpure( const Expression * expr ) {
    113         return detectImpurity( expr, false );
    114 }
    115 
    116 bool maybeImpureIgnoreUnique( const Expression * expr ) {
    117         return detectImpurity( expr, true );
    118 }
    119 
    12063} // namespace Tuples
    12164
  • src/Tuples/Tuples.h

    r790d835 rc6b4432  
    2121#include "AST/Fwd.hpp"
    2222#include "AST/Node.hpp"
    23 #include "SynTree/Expression.h"
    24 #include "SynTree/Declaration.h"
    25 #include "SynTree/Type.h"
    26 
    27 #include "ResolvExpr/AlternativeFinder.h"
    2823#include "ResolvExpr/CandidateFinder.hpp"
    2924
    3025namespace Tuples {
    3126        // TupleAssignment.cc
    32         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign,
    33                 std::vector< ResolvExpr::AlternativeFinder >& args );
    3427        void handleTupleAssignment(
    3528                ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
     
    3831        // TupleExpansion.cc
    3932        /// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate
    40         void expandMemberTuples( std::list< Declaration * > & translationUnit );
    4133        void expandMemberTuples( ast::TranslationUnit & translationUnit );
    4234
    4335        /// replaces tuple-related elements, such as TupleType, TupleExpr, TupleAssignExpr, etc.
    44         void expandTuples( std::list< Declaration * > & translationUnit );
    4536        void expandTuples( ast::TranslationUnit & translaionUnit );
    4637
    4738        /// replaces UniqueExprs with a temporary variable and one call
    48         void expandUniqueExpr( std::list< Declaration * > & translationUnit );
    4939        void expandUniqueExpr( ast::TranslationUnit & translationUnit );
    5040
    5141        /// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
    52         Type * makeTupleType( const std::list< Expression * > & exprs );
    5342        const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs );
    5443
    5544        /// returns a TypeInstType if `type` is a ttype, nullptr otherwise
    56         TypeInstType * isTtype( Type * type );
    57         const TypeInstType * isTtype( const Type * type );
    5845        const ast::TypeInstType * isTtype( const ast::Type * type );
    5946
    6047        /// returns true if the expression may contain side-effects.
    61         bool maybeImpure( const Expression * expr );
    6248        bool maybeImpure( const ast::Expr * expr );
    6349
    6450        /// Returns true if the expression may contain side-effect,
    6551        /// ignoring the presence of unique expressions.
    66         bool maybeImpureIgnoreUnique( const Expression * expr );
    6752        bool maybeImpureIgnoreUnique( const ast::Expr * expr );
    6853} // namespace Tuples
Note: See TracChangeset for help on using the changeset viewer.