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

Remove BaseSyntaxNode? and clean-up.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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 {
Note: See TracChangeset for help on using the changeset viewer.