source: src/ControlStruct/CaseRangeMutator.cc @ 4e06c1e

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 4e06c1e was 4e06c1e, checked in by Peter A. Buhr <pabuhr@…>, 7 years ago

changes for switch and choose statements

  • Property mode set to 100644
File size: 6.1 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// CaseRangeMutator.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 : Tue Jul 12 17:35:13 2016
13// Update Count     : 9
14//
15
16#include <list>
17#include <cassert>
18#include <cstdlib>
19#include <iterator>
20
21#include "Common/utility.h"
22
23#include "SynTree/Statement.h"
24#include "SynTree/Expression.h"
25#include "SynTree/Constant.h"
26#include "SynTree/Type.h"
27#include "CaseRangeMutator.h"
28
29namespace ControlStruct {
30        Statement *CaseRangeMutator::mutate( SwitchStmt *switchStmt ) {
31                std::list< Statement * > &cases = switchStmt->get_branches();
32
33                // a `for' would be more natural... all this contortions are because `replace' invalidates the iterator
34                std::list< Statement * >::iterator i = cases.begin();
35                while ( i != cases.end() ) {
36                        (*i )->acceptMutator( *this );
37
38                        if ( ! newCaseLabels.empty() ) {
39                                std::list< Statement * > newCases;
40
41                                // transform( newCaseLabels.begin(), newCaseLabels.end(), bnd1st( ptr_fun( ctor< CaseStmt, Label, Expression * > ) ) );
42
43                                for ( std::list< Expression * >::iterator j = newCaseLabels.begin();
44                                          j != newCaseLabels.end(); j++ ) {
45                                        std::list<Label> emptyLabels;
46                                        std::list< Statement *> emptyStmts;
47                                        newCases.push_back( new CaseStmt( emptyLabels, *j, emptyStmts ) );
48                                } // for
49
50                                if ( CaseStmt *currentCase = dynamic_cast< CaseStmt * > ( *i ) )
51                                        if ( ! currentCase->get_statements().empty() ) {
52                                                CaseStmt *lastCase = dynamic_cast< CaseStmt * > ( newCases.back() );
53                                                if ( lastCase == 0 ) { throw ( 0 ); /* FIXME */ } // something is very wrong, as I just made these, and they were all cases
54                                                // transfer the statement block ( if any ) to the new list:
55                                                lastCase->set_statements( currentCase->get_statements() );
56                                        } // if
57                                std::list< Statement * >::iterator j = i; advance( j, 1 );
58                                replace ( cases, i, newCases );
59                                i = j;
60                                newCaseLabels.clear();
61                        } else
62                                i++;
63                } // while
64
65                return switchStmt;
66        }
67
68        Statement *CaseRangeMutator::mutate( CaseStmt *caseStmt ) {
69                UntypedExpr *cond;
70                if ( ( cond = dynamic_cast< UntypedExpr * >( caseStmt->get_condition() )) != 0 ) {
71                        NameExpr *nmfunc;
72                        if ( ( nmfunc = dynamic_cast< NameExpr *>( cond->get_function() )) != 0 ) {
73                                if ( nmfunc->get_name() == std::string("Range") ) {
74                                        assert( cond->get_args().size() == 2 );
75                                        std::list<Expression *>::iterator i = cond->get_args().begin();
76                                        Expression *lo = *i, *hi = *(++i ); // "unnecessary" temporaries
77                                        fillRange( lo, hi );
78                                } // if
79                        } // if
80                } else if ( TupleExpr *tcond = dynamic_cast< TupleExpr * >( caseStmt->get_condition() ) ) {
81                        // case list
82                        assert( ! tcond->get_exprs().empty() );
83                        for ( std::list< Expression * >::iterator i = tcond->get_exprs().begin(); i != tcond->get_exprs().end(); i++ )
84                                newCaseLabels.push_back( *i ); // do I need to clone them?
85                } // if
86
87                std::list< Statement * > &stmts = caseStmt->get_statements();
88                mutateAll ( stmts, *this );
89
90                return caseStmt;
91        }
92
93        void CaseRangeMutator::fillRange( Expression *lo, Expression *hi ) {
94                // generate the actual range ( and check for consistency )
95                Constant *c_lo, *c_hi;
96                ConstantExpr *ce_lo, *ce_hi;
97                ce_lo = dynamic_cast< ConstantExpr * >( lo );
98                ce_hi = dynamic_cast< ConstantExpr * >( hi );
99
100                if ( ce_lo && ce_hi ) {
101                        c_lo = ce_lo->get_constant(); c_hi = ce_hi->get_constant();
102                } /* else {
103                         if ( ! ce_lo ) ;
104                         if ( ! ce_hi ) ;
105                         } */
106                BasicType *ty_lo = dynamic_cast< BasicType * >( c_lo->get_type() ),
107                        *ty_hi = dynamic_cast< BasicType * >( c_hi->get_type() );
108       
109                if ( ! ty_lo || ! ty_hi )
110                        return; // one of them is not a constant
111
112                switch ( ty_lo->get_kind() ) {
113                  case BasicType::Char:
114                  case BasicType::UnsignedChar:
115                        switch ( ty_hi->get_kind() ) {
116                          case BasicType::Char:
117                          case BasicType::UnsignedChar:
118                                // first case, they are both printable ASCII characters represented as 'x'
119                                if ( c_lo->get_value().size() == 3 && c_hi->get_value().size() == 3 ) {
120                                        char ch_lo = ( c_lo->get_value())[1], ch_hi = ( c_hi->get_value())[1];
121
122                                        if ( ch_lo > ch_hi ) { char t=ch_lo; ch_lo=ch_hi; ch_hi=t; }
123
124                                        for ( char c = ch_lo; c <=  ch_hi; c++ ) {
125                                                Type::Qualifiers q;
126                                                Constant cnst( new BasicType( q, BasicType::Char ),
127                                                                           std::string("'") + c + std::string("'") );
128                                                newCaseLabels.push_back( new ConstantExpr( cnst ) );
129                                        } // for
130
131                                        return;
132                                } // if
133                                break;
134                          default:
135                                // error: incompatible constants
136                                break;
137                        } // switch
138                        break;
139                  case BasicType::ShortSignedInt:
140                  case BasicType::ShortUnsignedInt:
141                  case BasicType::SignedInt:
142                  case BasicType::UnsignedInt:
143                  case BasicType::LongSignedInt:
144                  case BasicType::LongUnsignedInt:
145                  case BasicType::LongLongSignedInt:
146                  case BasicType::LongLongUnsignedInt:
147                        switch ( ty_hi->get_kind() ) {
148                          case BasicType::ShortSignedInt:
149                          case BasicType::ShortUnsignedInt:
150                          case BasicType::SignedInt:
151                          case BasicType::UnsignedInt:
152                          case BasicType::LongSignedInt:
153                          case BasicType::LongUnsignedInt:
154                          case BasicType::LongLongSignedInt:
155                          case BasicType::LongLongUnsignedInt: {
156                                  int i_lo = atoi( c_lo->get_value().c_str()),
157                                          i_hi = atoi( c_hi->get_value().c_str());
158
159                                  if ( i_lo > i_hi ) { int t=i_lo; i_lo=i_hi; i_hi=t; }
160
161                                  for ( int c = i_lo; c <=  i_hi; c++ ) {
162                                          Type::Qualifiers q;
163                                          Constant cnst( new BasicType( q, ty_hi->get_kind()), // figure can't hurt (used to think in positives)
164                                                                         toString< int >( c ) );
165                                          newCaseLabels.push_back( new ConstantExpr( cnst ) );
166                                  }
167
168                                  return;
169                          }
170                          default:
171                                // error: incompatible constants
172                                break;
173                        }
174                        break;
175                  default:
176                        break;
177                } // switch
178
179                /* End: */{ 
180                        // invalid range, signal a warning (it still generates the two case labels)
181                        newCaseLabels.push_back( lo );
182                        newCaseLabels.push_back( hi );
183                        return;
184                }
185        }
186} // namespace ControlStruct
187
188// Local Variables: //
189// tab-width: 4 //
190// mode: c++ //
191// compile-command: "make install" //
192// End: //
Note: See TracBrowser for help on using the repository browser.