Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleExpansionNew.cpp

    r36cb4d9 re9e9f56  
    1010// Created On       : Mon Aug 23 15:36:09 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Sep 26 10:25:00 2022
    13 // Update Count     : 5
     12// Last Modified On : Tue Sep 20 16:17:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    3030struct UniqueExprExpander final : public ast::WithDeclsToAdd<> {
    3131        const ast::Expr * postvisit( const ast::UniqueExpr * unqExpr );
    32         // Not a vector, because they may not be adding in increasing order.
    33         std::map< int, ast::ptr<ast::Expr> > decls;
    34 };
    35 
    36 /// Replaces Tuple Assign & Index Expressions, and Tuple Types.
    37 struct TupleMainExpander final :
    38                 public ast::WithCodeLocation,
    39                 public ast::WithDeclsToAdd<>,
    40                 public ast::WithGuards,
    41                 public ast::WithVisitorRef<TupleMainExpander> {
    42         ast::Expr const * postvisit( ast::TupleAssignExpr const * expr );
    43 
    44         void previsit( ast::CompoundStmt const * );
    45         ast::Expr const * postvisit( ast::Expr const * expr );
    46         ast::Type const * postvisit( ast::TupleType const * type );
    47 
    48         ast::Expr const * postvisit( ast::TupleIndexExpr const * expr );
    49 private:
    50         ScopedMap< int, ast::StructDecl const * > typeMap;
    51 };
    52 
    53 struct TupleExprExpander final {
    54         ast::Expr const * postvisit( ast::TupleExpr const * expr );
     32        std::map< int, ast::ptr<ast::Expr> > decls; // not vector, because order added may not be increasing order
    5533};
    5634
     
    122100}
    123101
    124 // Handles expansion of tuple assignment.
    125 ast::Expr const * TupleMainExpander::postvisit(
    126                 ast::TupleAssignExpr const * expr ) {
    127         // Just move the env on the new top level expression.
    128         return ast::mutate_field( expr->stmtExpr.get(),
    129                 &ast::TupleAssignExpr::env, expr->env.get() );
    130 }
    131 
    132 // Context information for tuple type expansion.
    133 void TupleMainExpander::previsit( ast::CompoundStmt const * ) {
    134         GuardScope( typeMap );
    135 }
    136 
    137 // Make sure types in a TypeSubstitution are expanded.
    138 ast::Expr const * TupleMainExpander::postvisit( ast::Expr const * expr ) {
    139         if ( nullptr == expr->env ) {
    140                 return expr;
    141         }
    142         return ast::mutate_field( expr, &ast::Expr::env,
    143                 expr->env->accept( *visitor ) );
    144 }
    145 
    146 // Create a generic tuple structure of a given size.
    147 ast::StructDecl * createTupleStruct(
    148                 unsigned int tupleSize, CodeLocation const & location ) {
    149         ast::StructDecl * decl = new ast::StructDecl( location,
    150                 toString( "_tuple", tupleSize, "_" )
    151         );
    152         decl->body = true;
    153 
    154         for ( size_t i = 0 ; i < tupleSize ; ++i ) {
    155                 ast::TypeDecl * typeParam = new ast::TypeDecl( location,
    156                         toString( "tuple_param_", tupleSize, "_", i ),
    157                         ast::Storage::Classes(),
    158                         nullptr,
    159                         ast::TypeDecl::Dtype,
    160                         true
     102/// Replaces Tuple Assign & Index Expressions, and Tuple Types.
     103struct TupleMainExpander final :
     104                public ast::WithCodeLocation,
     105                public ast::WithDeclsToAdd<>,
     106                public ast::WithGuards,
     107                public ast::WithVisitorRef<TupleMainExpander> {
     108        ast::Expr const * postvisit( ast::TupleAssignExpr const * expr ) {
     109                // Just move the env on the new top level expression.
     110                return ast::mutate_field( expr->stmtExpr.get(),
     111                        &ast::TupleAssignExpr::env, expr->env.get() );
     112        }
     113
     114        void previsit( ast::CompoundStmt const * ) {
     115                GuardScope( typeMap );
     116        }
     117
     118        ast::Expr const * postvisit( ast::Expr const * expr ) {
     119                if ( nullptr == expr->env ) {
     120                        return expr;
     121                }
     122                // TypeSubstitutions are never visited in the new Pass template,
     123                // so it is done manually here, where all types have to be replaced.
     124                return ast::mutate_field( expr, &ast::Expr::env,
     125                        expr->env->accept( *visitor ) );
     126        }
     127
     128        ast::Type const * postvisit( ast::TupleType const * type ) {
     129                assert( location );
     130                unsigned tupleSize = type->size();
     131                if ( !typeMap.count( tupleSize ) ) {
     132                        ast::StructDecl * decl = new ast::StructDecl( *location,
     133                                toString( "_tuple", tupleSize, "_" )
    161134                        );
    162                 ast::ObjectDecl * member = new ast::ObjectDecl( location,
    163                         toString( "field_", i ),
    164                         new ast::TypeInstType( typeParam )
    165                         );
    166                 decl->params.push_back( typeParam );
    167                 decl->members.push_back( member );
    168         }
    169 
    170         // Empty structures are not standard C. Add a dummy field to
    171         // empty tuples to silence warnings when a compound literal
    172         // `_tuple0_` is created.
    173         if ( tupleSize == 0 ) {
    174                 decl->members.push_back(
    175                         new ast::ObjectDecl( location,
    176                                 "dummy",
    177                                 new ast::BasicType( ast::BasicType::SignedInt ),
    178                                 nullptr,
    179                                 ast::Storage::Classes(),
    180                                 // Does this have to be a C linkage?
    181                                 ast::Linkage::C
    182                         )
    183                 );
    184         }
    185         return decl;
    186 }
    187 
    188 ast::Type const * TupleMainExpander::postvisit( ast::TupleType const * type ) {
    189         assert( location );
    190         unsigned tupleSize = type->size();
    191         if ( !typeMap.count( tupleSize ) ) {
    192                 ast::StructDecl * decl = createTupleStruct( tupleSize, *location );
    193                 typeMap[tupleSize] = decl;
    194                 declsToAddBefore.push_back( decl );
    195         }
    196 
    197         ast::StructDecl const * decl = typeMap[ tupleSize ];
    198         ast::StructInstType * newType =
    199                 new ast::StructInstType( decl, type->qualifiers );
    200         for ( auto pair : group_iterate( type->types, decl->params ) ) {
    201                 ast::Type const * t = std::get<0>( pair );
    202                 newType->params.push_back(
    203                         new ast::TypeExpr( *location, ast::deepCopy( t ) ) );
    204         }
    205         return newType;
    206 }
    207 
    208 // Expand a tuple index into a field access in the underlying structure.
    209 ast::Expr const * TupleMainExpander::postvisit(
    210                 ast::TupleIndexExpr const * expr ) {
    211         CodeLocation const & location = expr->location;
    212         ast::Expr const * tuple = expr->tuple.get();
    213         assert( tuple );
    214         unsigned int index = expr->index;
    215         ast::TypeSubstitution const * env = expr->env.get();
    216 
    217         if ( auto tupleExpr = dynamic_cast<ast::TupleExpr const *>( tuple ) ) {
    218                 // Optimization: If it is a definitely pure tuple expr,
    219                 // then it can reduce to the only relevant component.
    220                 if ( !maybeImpureIgnoreUnique( tupleExpr ) ) {
    221                         assert( index < tupleExpr->exprs.size() );
    222                         ast::ptr<ast::Expr> const & expr =
    223                                 *std::next( tupleExpr->exprs.begin(), index );
    224                         ast::Expr * ret = ast::mutate( expr.get() );
    225                         ret->env = env;
    226                         return ret;
    227                 }
    228         }
    229 
    230         auto type = tuple->result.strict_as<ast::StructInstType>();
    231         ast::StructDecl const * structDecl = type->base;
    232         assert( index < structDecl->members.size() );
    233         ast::ptr<ast::Decl> const & member =
    234                 *std::next( structDecl->members.begin(), index );
    235         ast::MemberExpr * memberExpr = new ast::MemberExpr( location,
    236                 member.strict_as<ast::DeclWithType>(), tuple );
    237         memberExpr->env = env;
    238         return memberExpr;
    239 }
     135                        decl->body = true;
     136
     137                        for ( size_t i = 0 ; i < tupleSize ; ++i ) {
     138                                ast::TypeDecl * typeParam = new ast::TypeDecl( *location,
     139                                        toString( "tuple_param_", tupleSize, "_", i ),
     140                                        ast::Storage::Classes(),
     141                                        nullptr,
     142                                        ast::TypeDecl::Dtype,
     143                                        true
     144                                        );
     145                                ast::ObjectDecl * member = new ast::ObjectDecl( *location,
     146                                        toString( "field_", i ),
     147                                        new ast::TypeInstType( typeParam )
     148                                        );
     149                                decl->params.push_back( typeParam );
     150                                decl->members.push_back( member );
     151                        }
     152
     153                        // Empty structures are not standard C. Add a dummy field to
     154                        // empty tuples to silence warnings when a compound literal
     155                        // `_tuple0_` is created.
     156                        if ( tupleSize == 0 ) {
     157                                decl->members.push_back(
     158                                        new ast::ObjectDecl( *location,
     159                                                "dummy",
     160                                                new ast::BasicType( ast::BasicType::SignedInt ),
     161                                                nullptr,
     162                                                ast::Storage::Classes(),
     163                                                // Does this have to be a C linkage?
     164                                                ast::Linkage::C
     165                                        )
     166                                );
     167                        }
     168                        typeMap[tupleSize] = decl;
     169                        declsToAddBefore.push_back( decl );
     170                }
     171
     172                ast::StructDecl const * decl = typeMap[ tupleSize ];
     173                ast::StructInstType * newType =
     174                        new ast::StructInstType( decl, type->qualifiers );
     175                for ( auto pair : group_iterate( type->types, decl->params ) ) {
     176                        ast::Type const * t = std::get<0>( pair );
     177                        newType->params.push_back(
     178                                new ast::TypeExpr( *location, ast::deepCopy( t ) ) );
     179                }
     180                return newType;
     181        }
     182
     183        ast::Expr const * postvisit( ast::TupleIndexExpr const * expr ) {
     184                CodeLocation const & location = expr->location;
     185                ast::Expr const * tuple = expr->tuple.get();
     186                assert( tuple );
     187                unsigned int index = expr->index;
     188                ast::TypeSubstitution const * env = expr->env.get();
     189
     190                if ( auto tupleExpr = dynamic_cast<ast::TupleExpr const *>( tuple ) ) {
     191                        // Optimization: If it is a definitely pure tuple expr,
     192                        // then it can reduce to the only relevant component.
     193                        if ( !maybeImpureIgnoreUnique( tupleExpr ) ) {
     194                                assert( index < tupleExpr->exprs.size() );
     195                                ast::ptr<ast::Expr> const & expr =
     196                                        *std::next( tupleExpr->exprs.begin(), index );
     197                                ast::Expr * ret = ast::mutate( expr.get() );
     198                                ret->env = env;
     199                                return ret;
     200                        }
     201                }
     202
     203                auto type = tuple->result.strict_as<ast::StructInstType>();
     204                ast::StructDecl const * structDecl = type->base;
     205                assert( index < structDecl->members.size() );
     206                ast::ptr<ast::Decl> const & member =
     207                        *std::next( structDecl->members.begin(), index );
     208                ast::MemberExpr * memberExpr = new ast::MemberExpr( location,
     209                        member.strict_as<ast::DeclWithType>(), tuple );
     210                memberExpr->env = env;
     211                return memberExpr;
     212        }
     213private:
     214        ScopedMap< int, ast::StructDecl const * > typeMap;
     215};
    240216
    241217ast::Expr const * replaceTupleExpr(
     
    273249}
    274250
    275 ast::Expr const * TupleExprExpander::postvisit( ast::TupleExpr const * expr ) {
    276         return replaceTupleExpr( expr->location,
    277                 expr->result, expr->exprs, expr->env );
    278 }
     251struct TupleExprExpander final {
     252        ast::Expr const * postvisit( ast::TupleExpr const * expr ) {
     253                return replaceTupleExpr( expr->location,
     254                        expr->result, expr->exprs, expr->env );
     255        }
     256};
    279257
    280258} // namespace
Note: See TracChangeset for help on using the changeset viewer.