source: src/ControlStruct/CaseRangeMutator.cc @ ca35c51

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since ca35c51 was ca35c51, checked in by Peter A. Buhr <pabuhr@…>, 8 years ago

move implementation of ConstantNode? to ConstantExpr?

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