source: src/Tuples/Explode.cpp@ 85855b0

Last change on this file since 85855b0 was c92bdcc, checked in by Andrew Beach <ajbeach@…>, 16 months ago

Updated the rest of the names in src/ (except for the generated files).

  • Property mode set to 100644
File size: 3.6 KB
Line 
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.cpp --
8//
9// Author : Rob Schluntz
10// Created On : Wed Nov 9 13:12:24 2016
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Jun 12 16:40:00 2016
13// Update Count : 3
14//
15
16#include "Explode.hpp"
17
18#include "AST/Pass.hpp" // for Pass
19
20namespace Tuples {
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;
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 } };
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;
58 return new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
59 }
60 }
61
62 const ast::Expr * postvisit( const ast::UniqueExpr * node ) {
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 );
76 return new ast::CastExpr{ newNode->location, newNode, newType };
77 }
78 return newNode;
79 }
80
81 const ast::Expr * postvisit( const ast::TupleIndexExpr * tupleExpr ) {
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 );
94 if ( ! exploder.core.foundUniqueExpr ) {
95 expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
96 }
97 return expr;
98}
99
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.