Changeset b507dcd


Ignore:
Timestamp:
Jul 29, 2022, 12:15:29 PM (20 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, master, pthread-emulation
Children:
ce1d721
Parents:
d0fcc82
Message:

Converted the Expand Tuples pass to the new ast.

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleExpansionNew.cpp

    rd0fcc82 rb507dcd  
    1515
    1616#include "Tuples.h"
     17
     18#include "AST/Pass.hpp"
     19#include "Common/ScopedMap.h"
    1720
    1821namespace Tuples {
     
    111114        }
    112115} // namespace
     116
     117namespace {
     118
     119struct TupleAssignExpander {
     120        ast::Expr const * postvisit( ast::TupleAssignExpr const * expr ) {
     121                // Just move the env on the new top level expression.
     122                return ast::mutate_field( expr->stmtExpr.get(),
     123                        &ast::TupleAssignExpr::env, expr->env.get() );
     124        }
     125};
     126
     127struct TupleTypeReplacer :
     128                public ast::WithGuards,
     129                public ast::WithVisitorRef<TupleTypeReplacer>,
     130                public ast::WithDeclsToAdd<> {
     131        void previsit( ast::ParseNode const * node ) {
     132                GuardValue( location ) = &node->location;
     133        }
     134
     135        void previsit( ast::CompoundStmt const * stmt ) {
     136                previsit( (ast::ParseNode const *)stmt );
     137                GuardScope( typeMap );
     138        }
     139
     140        ast::Expr const * postvisit( ast::Expr const * expr ) {
     141                if ( nullptr == expr->env ) {
     142                        return expr;
     143                }
     144                // TypeSubstitutions are never visited in the new Pass template,
     145                // so it is done manually here, where all types have to be replaced.
     146                return ast::mutate_field( expr, &ast::Expr::env,
     147                        expr->env->accept( *visitor ) );
     148        }
     149
     150        ast::Type const * postvisit( ast::TupleType const * type ) {
     151                assert( location );
     152                unsigned tupleSize = type->size();
     153                if ( !typeMap.count( tupleSize ) ) {
     154                        ast::StructDecl * decl = new ast::StructDecl( *location,
     155                                toString( "_tuple", tupleSize, "_" )
     156                        );
     157                        decl->body = true;
     158
     159                        for ( size_t i = 0 ; i < tupleSize ; ++i ) {
     160                                ast::TypeDecl * typeParam = new ast::TypeDecl( *location,
     161                                        toString( "tuple_param_", tupleSize, "_", i ),
     162                                        ast::Storage::Classes(),
     163                                        nullptr,
     164                                        ast::TypeDecl::Dtype,
     165                                        true
     166                                        );
     167                                ast::ObjectDecl * member = new ast::ObjectDecl( *location,
     168                                        toString( "field_", i ),
     169                                        new ast::TypeInstType( typeParam )
     170                                        );
     171                                decl->params.push_back( typeParam );
     172                                decl->members.push_back( member );
     173                        }
     174
     175                        // Empty structures are not standard C. Add a dummy field to
     176                        // empty tuples to silence warnings when a compound literal
     177                        // `_tuple0_` is created.
     178                        if ( tupleSize == 0 ) {
     179                                decl->members.push_back(
     180                                        new ast::ObjectDecl( *location,
     181                                                "dummy",
     182                                                new ast::BasicType( ast::BasicType::SignedInt ),
     183                                                nullptr,
     184                                                ast::Storage::Classes(),
     185                                                // Does this have to be a C linkage?
     186                                                ast::Linkage::C
     187                                        )
     188                                );
     189                        }
     190                        typeMap[tupleSize] = decl;
     191                        declsToAddBefore.push_back( decl );
     192                }
     193
     194                ast::StructDecl const * decl = typeMap[ tupleSize ];
     195                ast::StructInstType * newType =
     196                        new ast::StructInstType( decl, type->qualifiers );
     197                for ( auto pair : group_iterate( type->types, decl->params ) ) {
     198                        ast::Type const * t = std::get<0>( pair );
     199                        newType->params.push_back(
     200                                new ast::TypeExpr( *location, ast::deepCopy( t ) ) );
     201                }
     202                return newType;
     203        }
     204private:
     205        ScopedMap< int, ast::StructDecl const * > typeMap;
     206        CodeLocation const * location = nullptr;
     207};
     208
     209struct TupleIndexExpander {
     210        ast::Expr const * postvisit( 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        }
     240};
     241
     242ast::Expr const * replaceTupleExpr(
     243                CodeLocation const & location,
     244                ast::Type const * result,
     245                std::vector<ast::ptr<ast::Expr>> const & exprs,
     246                ast::TypeSubstitution const * env ) {
     247        assert( result );
     248        // A void result: It doesn't need to produce a value for cascading,
     249        // just output a chain of comma exprs.
     250        if ( result->isVoid() ) {
     251                assert( !exprs.empty() );
     252                std::vector<ast::ptr<ast::Expr>>::const_iterator iter = exprs.begin();
     253                ast::Expr * expr = new ast::CastExpr( *iter++ );
     254                for ( ; iter != exprs.end() ; ++iter ) {
     255                        expr = new ast::CommaExpr( location,
     256                                expr, new ast::CastExpr( *iter ) );
     257                }
     258                expr->env = env;
     259                return expr;
     260        // Typed tuple expression: Produce a compound literal which performs
     261        // each of the expressions as a distinct part of its initializer. The
     262        // produced compound literal may be used as part of another expression.
     263        } else {
     264                auto inits = map_range<std::vector<ast::ptr<ast::Init>>>( exprs,
     265                        []( ast::Expr const * expr ) {
     266                                return new ast::SingleInit( expr->location, expr );
     267                        }
     268                );
     269                ast::Expr * expr = new ast::CompoundLiteralExpr( location,
     270                        result, new ast::ListInit( location, std::move( inits ) ) );
     271                expr->env = env;
     272                return expr;
     273        }
     274}
     275
     276struct TupleExprExpander {
     277        ast::Expr const * postvisit( ast::TupleExpr const * expr ) {
     278                return replaceTupleExpr( expr->location,
     279                        expr->result, expr->exprs, expr->env );
     280        }
     281};
     282
     283} // namespace
     284
     285void expandTuples( ast::TranslationUnit & translationUnit ) {
     286        // These may not have to be seperate passes.
     287        ast::Pass<TupleAssignExpander>::run( translationUnit );
     288        ast::Pass<TupleTypeReplacer>::run( translationUnit );
     289        ast::Pass<TupleIndexExpander>::run( translationUnit );
     290        ast::Pass<TupleExprExpander>::run( translationUnit );
     291}
     292
    113293} // namespace Tuples
  • src/Tuples/Tuples.h

    rd0fcc82 rb507dcd  
    3232        void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign,
    3333                std::vector< ResolvExpr::AlternativeFinder >& args );
    34         void handleTupleAssignment( 
    35                 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 
     34        void handleTupleAssignment(
     35                ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
    3636                std::vector< ResolvExpr::CandidateFinder > & args );
    3737
     
    4343        /// replaces tuple-related elements, such as TupleType, TupleExpr, TupleAssignExpr, etc.
    4444        void expandTuples( std::list< Declaration * > & translationUnit );
     45        void expandTuples( ast::TranslationUnit & translaionUnit );
    4546
    4647        /// replaces UniqueExprs with a temporary variable and one call
  • src/main.cc

    rd0fcc82 rb507dcd  
    443443                        PASS( "Convert Specializations",  GenPoly::convertSpecializations( transUnit ) );
    444444
     445                        PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) );
     446
    445447                        translationUnit = convert( move( transUnit ) );
    446448                } else {
     
    517519                        PASS( "Gen Waitfor", Concurrency::generateWaitFor( translationUnit ) );
    518520                        PASS( "Convert Specializations",  GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded
     521                        PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?
    519522                }
    520 
    521                 PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?
    522523
    523524                if ( tuplep ) {
Note: See TracChangeset for help on using the changeset viewer.