source: src/Tuples/TupleAssignment.cc@ aefcc3b

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since aefcc3b was 3c13c03, checked in by Rob Schluntz <rschlunt@…>, 9 years ago

expand TupleExpr and TupleIndexExpr, add UniqueExpr

  • Property mode set to 100644
File size: 8.5 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// TupleAssignment.cc --
8//
9// Author : Rodolfo G. Esteves
10// Created On : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Mon May 18 15:02:53 2015
13// Update Count : 2
14//
15
16#include "ResolvExpr/AlternativeFinder.h"
17#include "ResolvExpr/Alternative.h"
18#include "ResolvExpr/typeops.h"
19#include "SynTree/Expression.h"
20#include "SynTree/Initializer.h"
21#include "Tuples.h"
22#include "Common/SemanticError.h"
23
24#include <functional>
25#include <algorithm>
26#include <iterator>
27#include <iostream>
28#include <cassert>
29#include <set>
30#include <unordered_set>
31
32namespace Tuples {
33 class TupleAssignSpotter {
34 public:
35 // dispatcher for Tuple (multiple and mass) assignment operations
36 TupleAssignSpotter( ResolvExpr::AlternativeFinder & );
37 void spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities );
38
39 private:
40 void match();
41
42 struct Matcher {
43 public:
44 Matcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );
45 virtual ~Matcher() {}
46 virtual void match( std::list< Expression * > &out ) = 0;
47 ResolvExpr::AltList lhs, rhs;
48 TupleAssignSpotter &spotter;
49 std::list< ObjectDecl * > tmpDecls;
50 };
51
52 struct MassAssignMatcher : public Matcher {
53 public:
54 MassAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );
55 virtual void match( std::list< Expression * > &out );
56 };
57
58 struct MultipleAssignMatcher : public Matcher {
59 public:
60 MultipleAssignMatcher( TupleAssignSpotter &spot, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs );
61 virtual void match( std::list< Expression * > &out );
62 };
63
64 ResolvExpr::AlternativeFinder &currentFinder;
65 // Expression *rhs, *lhs;
66 Matcher *matcher = nullptr;
67 };
68
69 /// true if expr is an expression of tuple type, i.e. a tuple expression, tuple variable, or MRV (multiple-return-value) function
70 bool isTuple( Expression *expr ) {
71 if ( ! expr ) return false;
72 assert( expr->has_result() );
73 return dynamic_cast<TupleExpr *>(expr) || expr->get_result()->size() > 1;
74 }
75
76 bool pointsToTuple( Expression *expr ) {
77 // also check for function returning tuple of reference types
78 if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) {
79 return isTuple( addr->get_arg() );
80 }
81 return false;
82 }
83
84 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
85 TupleAssignSpotter spotter( currentFinder );
86 spotter.spot( expr, possibilities );
87 }
88
89 TupleAssignSpotter::TupleAssignSpotter( ResolvExpr::AlternativeFinder &f )
90 : currentFinder(f) {}
91
92 void TupleAssignSpotter::spot( UntypedExpr * expr, std::list<ResolvExpr::AltList> &possibilities ) {
93 if ( NameExpr *assgnop = dynamic_cast< NameExpr * >(expr->get_function()) ) {
94 if ( assgnop->get_name() == "?=?" ) {
95 for ( std::list<ResolvExpr::AltList>::iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
96 if ( ali->size() != 2 ) continue; // what does it mean if an assignment takes >2 arguments? grab args 2-N and group into a TupleExpr, then proceed?
97 ResolvExpr::Alternative & alt1 = ali->front(), & alt2 = ali->back();
98
99 if ( pointsToTuple(alt1.expr) ) {
100 MultipleAssignMatcher multiMatcher( *this, alt1, alt2 );
101 MassAssignMatcher massMatcher( *this, alt1, alt2 );
102 if ( isTuple( alt2.expr ) ) {
103 matcher = &multiMatcher;
104 } else {
105 // mass assignment
106 matcher = &massMatcher;
107 }
108 match();
109 } else if ( isTuple( alt2.expr ) ) {
110 throw SemanticError("Cannot assign a tuple value into a non-tuple lvalue.", expr);
111 }
112 }
113 }
114 }
115 }
116
117 void TupleAssignSpotter::match() {
118 assert ( matcher != 0 );
119
120 std::list< Expression * > new_assigns;
121 matcher->match( new_assigns );
122
123 if ( new_assigns.empty() ) return;
124 ResolvExpr::AltList current;
125 // now resolve new assignments
126 for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
127 ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
128 finder.findWithAdjustment(*i);
129 // prune expressions that don't coincide with
130 ResolvExpr::AltList alts = finder.get_alternatives();
131 assert( alts.size() == 1 );
132 assert( alts.front().expr != 0 );
133 current.push_back( alts.front() );
134 }
135
136 // extract expressions from the assignment alternatives to produce a list of assignments that
137 // together form a single alternative
138 std::list< Expression *> solved_assigns;
139 for ( ResolvExpr::Alternative & alt : current ) {
140 solved_assigns.push_back( alt.expr->clone() );
141 }
142 // xxx - need to do this??
143 // TypeEnvironment compositeEnv;
144 // simpleCombineEnvironments( i->begin(), i->end(), compositeEnv );
145 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), currentFinder.get_environ(), ResolvExpr::sumCost( current ) ) );
146 }
147
148 TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : spotter(spotter) {
149 if (AddressExpr *addr = dynamic_cast<AddressExpr *>(lhs.expr) ) {
150 // xxx - not every assignment NEEDS to have the first argument as address-taken, e.g. a manual call to assignment. What to do in this case? skip it as a possibility for TupleAssignment, since the type will always be T*, where T can never be a tuple? Is this true?
151
152 // explode the lhs so that each field of the tuple-valued-expr is assigned.
153 ResolvExpr::Alternative lhsAlt( addr->get_arg()->clone(), lhs.env, lhs.cost, lhs.cvtCost );
154 explode( lhsAlt, back_inserter(this->lhs) );
155 }
156 }
157
158 TupleAssignSpotter::MassAssignMatcher::MassAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : Matcher( spotter, lhs, rhs ) {
159 this->rhs.push_back( rhs );
160 }
161
162 TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, ResolvExpr::Alternative & lhs, ResolvExpr::Alternative & rhs ) : Matcher( spotter, lhs, rhs ) {
163
164 // explode the rhs so that each field of the tuple-valued-expr is assigned.
165 explode( rhs, back_inserter(this->rhs) );
166 }
167
168 UntypedExpr * createAssgn( ObjectDecl *left, ObjectDecl *right ) {
169 assert( left && right );
170 std::list< Expression * > args;
171 args.push_back( new AddressExpr( new UntypedExpr( new NameExpr("*?"), std::list< Expression * >{ new VariableExpr( left ) } ) ) );
172 args.push_back( new VariableExpr( right ) );
173 return new UntypedExpr( new NameExpr( "?=?" ), args );
174 }
175
176 ObjectDecl * newObject( UniqueName & namer, Expression * expr ) {
177 assert( expr->has_result() && ! expr->get_result()->isVoid() );
178 return new ObjectDecl( namer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
179 }
180
181 void TupleAssignSpotter::MassAssignMatcher::match( std::list< Expression * > &out ) {
182 static UniqueName lhsNamer( "__massassign_L" );
183 static UniqueName rhsNamer( "__massassign_R" );
184 assert ( ! lhs.empty() && rhs.size() == 1);
185
186 ObjectDecl * rtmp = newObject( rhsNamer, rhs.front().expr );
187 for ( ResolvExpr::Alternative & lhsAlt : lhs ) {
188 ObjectDecl * ltmp = newObject( lhsNamer, new AddressExpr( lhsAlt.expr ) );
189 out.push_back( createAssgn( ltmp, rtmp ) );
190 tmpDecls.push_back( ltmp );
191 }
192 tmpDecls.push_back( rtmp );
193 }
194
195 void TupleAssignSpotter::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
196 static UniqueName lhsNamer( "__multassign_L" );
197 static UniqueName rhsNamer( "__multassign_R" );
198 // xxx - need more complicated matching?
199 if ( lhs.size() == rhs.size() ) {
200 std::list< ObjectDecl * > ltmp;
201 std::list< ObjectDecl * > rtmp;
202 std::transform( lhs.begin(), lhs.end(), back_inserter( ltmp ), []( ResolvExpr::Alternative & alt ){
203 return newObject( lhsNamer, new AddressExpr( alt.expr ) );
204 });
205 std::transform( rhs.begin(), rhs.end(), back_inserter( rtmp ), []( ResolvExpr::Alternative & alt ){
206 return newObject( rhsNamer, alt.expr );
207 });
208 zipWith( ltmp.begin(), ltmp.end(), rtmp.begin(), rtmp.end(), back_inserter(out), createAssgn );
209 tmpDecls.splice( tmpDecls.end(), ltmp );
210 tmpDecls.splice( tmpDecls.end(), rtmp );
211 }
212 }
213} // namespace Tuples
214
215// Local Variables: //
216// tab-width: 4 //
217// mode: c++ //
218// compile-command: "make install" //
219// End: //
Note: See TracBrowser for help on using the repository browser.