source: translator/ControlStruct/CaseRangeMutator.cc @ 42e2ad7

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

remove Parser.old, add -XCFA to driver, copy ptrdiff_t from stddef.h in preclude, remove casts from initialization constants, adjust formatting

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