source: src/Tuples/TupleAssignment.cc @ 1132b62

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 1132b62 was 3c13c03, checked in by Rob Schluntz <rschlunt@…>, 8 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.