source: src/Tuples/Explode.cc @ 0a9b5c1

Last change on this file since 0a9b5c1 was c6b4432, checked in by Andrew Beach <ajbeach@…>, 12 months ago

Remove BaseSyntaxNode? and clean-up.

  • Property mode set to 100644
File size: 3.6 KB
RevLine 
[141b786]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Explode.cc --
8//
9// Author           : Rob Schluntz
10// Created On       : Wed Nov 9 13:12:24 2016
[b910d15]11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Jun 12 16:40:00 2016
13// Update Count     : 3
[141b786]14//
15
16#include "Explode.h"
[03321e4]17
[bccd70a]18#include "AST/Pass.hpp"          // for Pass
[141b786]19
20namespace Tuples {
[b910d15]21
22namespace {
23
24// Remove one level of reference from a reference type.
25const ast::Type * getReferenceBase( const ast::Type * t ) {
26        if ( const ast::ReferenceType * ref = dynamic_cast< const ast::ReferenceType * >( t ) ) {
27                return ref->base;
28        } else {
29                assertf( false, "getReferenceBase for non-ref: %s", toString( t ).c_str() );
30                return nullptr;
31        }
32}
33
34struct CastExploderCore {
35        bool castAdded = false;
36        bool foundUniqueExpr = false;
37        const ast::Expr * applyCast( const ast::Expr * expr, bool first = true ) {
38                // On tuple push the cast down.
39                if ( const ast::TupleExpr * tupleExpr = dynamic_cast< const ast::TupleExpr * >( expr ) ) {
40                        foundUniqueExpr = true;
41                        std::vector< ast::ptr< ast::Expr > > exprs;
42                        for ( const ast::Expr * expr : tupleExpr->exprs ) {
43                                exprs.emplace_back( applyCast( expr, false ) );
44                        }
45                        if ( first ) {
46                                castAdded = true;
[b8524ca]47                                const ast::Expr * tuple = new ast::TupleExpr{
48                                        tupleExpr->location, std::move( exprs ) };
49                                return new ast::CastExpr{ tuple, new ast::ReferenceType{ tuple->result } };
[b910d15]50                        } else {
51                                return new ast::TupleExpr( tupleExpr->location, std::move( exprs ) );
52                        }
53                }
54                if ( dynamic_cast< const ast::ReferenceType * >( expr->result.get() ) ) {
55                        return expr;
56                } else {
57                        castAdded = true;
[b8524ca]58                        return new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
[b910d15]59                }
60        }
61
[c408483]62        const ast::Expr * postvisit( const ast::UniqueExpr * node ) {
[b910d15]63                // move cast into unique expr so that the unique expr has type T& rather than
64                // type T. In particular, this transformation helps with generating the
65                // correct code for reference-cast member tuple expressions, since the result
66                // should now be a tuple of references rather than a reference to a tuple.
67                // Still, this code is a bit awkward, and could use some improvement.
68                const ast::UniqueExpr * newNode = new ast::UniqueExpr( node->location,
69                                applyCast( node->expr ), node->id );
70                if ( castAdded ) {
71                        // if a cast was added by applyCast, then unique expr now has one more layer of reference
72                        // than it had coming into this function. To ensure types still match correctly, need to cast
73                        //  to reference base so that outer expressions are still correct.
74                        castAdded = false;
75                        const ast::Type * newType = getReferenceBase( newNode->result );
[74807be]76                        return new ast::CastExpr{ newNode->location, newNode, newType };
[b910d15]77                }
78                return newNode;
79        }
80
[c408483]81        const ast::Expr * postvisit( const ast::TupleIndexExpr * tupleExpr ) {
[b910d15]82                // tuple index expr needs to be rebuilt to ensure that the type of the
83                // field is consistent with the type of the tuple expr, since the field
84                // may have changed from type T to T&.
85                return new ast::TupleIndexExpr( tupleExpr->location, tupleExpr->tuple, tupleExpr->index );
86        }
87};
88
89} // namespace
90
91const ast::Expr * distributeReference( const ast::Expr * expr ) {
92        ast::Pass<CastExploderCore> exploder;
93        expr = expr->accept( exploder );
[7ff3e522]94        if ( ! exploder.core.foundUniqueExpr ) {
[b8524ca]95                expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
[b910d15]96        }
97        return expr;
98}
99
[141b786]100} // namespace Tuples
101
102// Local Variables: //
103// tab-width: 4 //
104// mode: c++ //
105// compile-command: "make install" //
106// End: //
Note: See TracBrowser for help on using the repository browser.