source: translator/ControlStruct/MLEMutator.cc @ c8ffe20b

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 c8ffe20b was 8c17ab0, checked in by Peter A. Buhr <pabuhr@…>, 10 years ago

add quoted identifiers, add compilation include directory, reformatted some files

  • Property mode set to 100644
File size: 6.9 KB
RevLine 
[51b7345]1#include <cassert>
2#include <algorithm>
3
4#include "MLEMutator.h"
5#include "SynTree/Statement.h"
6
7
8namespace ControlStruct {
9  MLEMutator::~MLEMutator()
10  {
11    delete targetTable;
12    targetTable = 0;
13  }
14
15  CompoundStmt* MLEMutator::mutate(CompoundStmt *cmpndStmt)
16  {
17    bool labeledBlock = false;
18    if (!((cmpndStmt->get_labels()).empty())) {
19      labeledBlock = true;
20      enclosingBlocks.push_back( Entry( cmpndStmt ) );
21    }
22
23    std::list< Statement * > &kids = cmpndStmt->get_kids();
24    for( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) {
25      *k = (*k)->acceptMutator(*this);
26
27      if (!get_breakLabel().empty()) {
28        std::list< Statement * >::iterator next = k; next++;
29        if( next == kids.end() ) {
30          std::list<Label> ls; ls.push_back( get_breakLabel() );
31          kids.push_back( new NullStmt(ls) );
32        } else
33          (*next)->get_labels().push_back( get_breakLabel() );
34
35        set_breakLabel("");
36      }
37    }
38
39    if ( labeledBlock ) {
40      assert( ! enclosingBlocks.empty() );
41      if( ! enclosingBlocks.back().get_breakExit().empty() )
42        set_breakLabel( enclosingBlocks.back().get_breakExit() );
43      enclosingBlocks.pop_back();
44    }
45
46    //mutateAll( cmpndStmt->get_kids(), *this );
47    return cmpndStmt;
48  }
49
50  Statement *MLEMutator::mutate( WhileStmt *whileStmt )
51  {
52    enclosingLoops.push_back( Entry( whileStmt ) );
53    whileStmt->set_body ( whileStmt->get_body()->acceptMutator( *this ) );
54
55    Entry &e = enclosingLoops.back();
56    assert ( e == whileStmt );
57    whileStmt->set_body( mutateLoop( whileStmt->get_body(), e ) );
58    enclosingLoops.pop_back();
59
60    return whileStmt;
61  }
62
63  Statement *MLEMutator::mutate( ForStmt *forStmt )
64  {
65    enclosingLoops.push_back( Entry( forStmt ) );
66    maybeMutate( forStmt->get_body(), *this );
67
68    Entry &e = enclosingLoops.back();
69    assert ( e == forStmt );
70    forStmt->set_body( mutateLoop( forStmt->get_body(), e ) );
71    enclosingLoops.pop_back();
72
73    return forStmt;
74  }
75
76  Statement *MLEMutator::mutate( BranchStmt *branchStmt )
77    throw ( SemanticError )
78  {
79    if ( branchStmt->get_type() == BranchStmt::Goto )
80      return branchStmt;
81
[8c17ab0]82    // test if continue target is a loop
[51b7345]83    if ( branchStmt->get_type() == BranchStmt::Continue && enclosingLoops.empty() )
84      throw SemanticError( "'continue' outside a loop" );
85
86  if ( branchStmt->get_type() == BranchStmt::Break && (enclosingLoops.empty() && enclosingSwitches.empty() && enclosingBlocks.empty() ) )
87      throw SemanticError( "'break' outside a loop or switch" );
88
89    if ( branchStmt->get_target() == "" ) return branchStmt;
90
91    if ( targetTable->find( branchStmt->get_target() ) == targetTable->end() )
92      throw SemanticError("The label defined in the exit loop statement does not exist." );  // shouldn't happen (since that's already checked)
93
94    std::list< Entry >::iterator check;
95    if ( ( check = std::find( enclosingLoops.begin(), enclosingLoops.end(), (*targetTable)[branchStmt->get_target()] ) ) == enclosingLoops.end() )
96      // not in loop, checking if in switch/choose
97      if ( (check = std::find( enclosingBlocks.begin(), enclosingBlocks.end(), (*targetTable)[branchStmt->get_target()] )) == enclosingBlocks.end() )
98        // neither in loop nor in block, checking if in switch/choose
99        if ( (check = std::find( enclosingSwitches.begin(), enclosingSwitches.end(), (*targetTable)[branchStmt->get_target()] )) == enclosingSwitches.end() )
100          throw SemanticError("The target specified in the exit loop statement does not correspond to an enclosing loop.");
101
102    if ( enclosingLoops.back() == (*check) )
103      return branchStmt;                      // exit the innermost loop (labels not necessary)
104
105    Label newLabel;
106    switch( branchStmt->get_type() ) {
107    case BranchStmt::Break:
108      if ( check->get_breakExit() != "" )
109        newLabel = check->get_breakExit();
110      else
111        { newLabel = generator->newLabel(); check->set_breakExit( newLabel ); }
112      break;
113    case BranchStmt::Continue:
114      if ( check->get_contExit() != "" )
115        newLabel = check->get_contExit();
116      else
117        { newLabel = generator->newLabel(); check->set_contExit( newLabel ); }
118      break;
119
120    default:
121      // shouldn't be here
122      return 0;
123    }
124
125    return new BranchStmt(std::list<Label>(), newLabel, BranchStmt::Goto );
126  }
127
128
129  Statement *MLEMutator::mutate(SwitchStmt *switchStmt)
130  {
131    Label brkLabel = generator->newLabel();
132    enclosingSwitches.push_back( Entry(switchStmt, "", brkLabel) );
133    mutateAll( switchStmt->get_branches(), *this );
134    {
135      // check if this is necessary (if there is a break to this point, otherwise do not generate
136      std::list<Label> temp; temp.push_back( brkLabel );
137      switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
138    }
139    assert ( enclosingSwitches.back() == switchStmt );
140    enclosingSwitches.pop_back();
141    return switchStmt;
142  }
143
144  Statement *MLEMutator::mutate(ChooseStmt *switchStmt)
145  {
146    Label brkLabel = generator->newLabel();
147    enclosingSwitches.push_back( Entry(switchStmt,"", brkLabel) );
148    mutateAll( switchStmt->get_branches(), *this );
149    {
150      // check if this is necessary (if there is a break to this point, otherwise do not generate
151      std::list<Label> temp; temp.push_back( brkLabel );
152      switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
153    }
154    assert ( enclosingSwitches.back() == switchStmt );
155    enclosingSwitches.pop_back();
156    return switchStmt;
157  }
158
159  Statement *MLEMutator::mutateLoop( Statement *bodyLoop, Entry &e ) {
160    CompoundStmt *newBody;
161    if ( ! (newBody = dynamic_cast<CompoundStmt *>( bodyLoop )) ) {
162      newBody = new CompoundStmt( std::list< Label >() );
163      newBody->get_kids().push_back( bodyLoop );
164    }
165
166    Label endLabel = e.get_contExit();
167
168    if ( e.get_breakExit() != "" ) {
169      if ( endLabel == "" ) endLabel = generator->newLabel();
170      // check for whether this label is used or not, so as to not generate extraneous gotos
171      if (e.breakExitUsed)
172        newBody->get_kids().push_back( new BranchStmt( std::list< Label >(), endLabel, BranchStmt::Goto ) );
173      // xxx
174      //std::list< Label > ls; ls.push_back( e.get_breakExit() );
175      set_breakLabel( e.get_breakExit() );
176      //newBody->get_kids().push_back( new BranchStmt( ls, "", BranchStmt::Break ) );
177    }
178
179    if ( e.get_breakExit() != "" || e.get_contExit() != "" ){
180      if(dynamic_cast< NullStmt *>( newBody->get_kids().back() ))
181        newBody->get_kids().back()->get_labels().push_back( endLabel );
182      else {
183        std::list < Label > ls; ls.push_back( endLabel );
184        newBody->get_kids().push_back( new NullStmt( ls ) );
185      }
186    }
187
188    return newBody;
189  }
190
191  //*** Entry's methods
192  void MLEMutator::Entry::set_contExit( Label l )
193  {
194    assert ( contExit == "" || contExit == l );
195    contExit = l;
196  }
197
198  void MLEMutator::Entry::set_breakExit( Label l )
199  {
200    assert ( breakExit == "" || breakExit == l );
201    breakExit = l;
202  }
203
204} // namespace ControlStruct
Note: See TracBrowser for help on using the repository browser.