Changeset 36cb4d9 for src/Tuples


Ignore:
Timestamp:
Sep 26, 2022, 10:32:56 AM (23 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, master
Children:
d3af505
Parents:
996c8ed
Message:

Reorganize the expandTuple pass to hopefully make it easier to follow.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleExpansionNew.cpp

    r996c8ed r36cb4d9  
    1010// Created On       : Mon Aug 23 15:36:09 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Sep 20 16:17:00 2022
    13 // Update Count     : 4
     12// Last Modified On : Mon Sep 26 10:25:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    3030struct UniqueExprExpander final : public ast::WithDeclsToAdd<> {
    3131        const ast::Expr * postvisit( const ast::UniqueExpr * unqExpr );
    32         std::map< int, ast::ptr<ast::Expr> > decls; // not vector, because order added may not be increasing order
     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.
     37struct 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 );
     49private:
     50        ScopedMap< int, ast::StructDecl const * > typeMap;
     51};
     52
     53struct TupleExprExpander final {
     54        ast::Expr const * postvisit( ast::TupleExpr const * expr );
    3355};
    3456
     
    100122}
    101123
    102 /// Replaces Tuple Assign & Index Expressions, and Tuple Types.
    103 struct 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, "_" )
     124// Handles expansion of tuple assignment.
     125ast::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.
     133void TupleMainExpander::previsit( ast::CompoundStmt const * ) {
     134        GuardScope( typeMap );
     135}
     136
     137// Make sure types in a TypeSubstitution are expanded.
     138ast::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.
     147ast::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
    134161                        );
    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         }
    213 private:
    214         ScopedMap< int, ast::StructDecl const * > typeMap;
    215 };
     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
     188ast::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.
     209ast::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}
    216240
    217241ast::Expr const * replaceTupleExpr(
     
    249273}
    250274
    251 struct 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 };
     275ast::Expr const * TupleExprExpander::postvisit( ast::TupleExpr const * expr ) {
     276        return replaceTupleExpr( expr->location,
     277                expr->result, expr->exprs, expr->env );
     278}
    257279
    258280} // namespace
Note: See TracChangeset for help on using the changeset viewer.