Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MLEMutator.cc

    r94e025a2 rba3706f  
    4646        void MLEMutator::fixBlock( std::list< Statement * > &kids ) {
    4747                for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) {
    48                         *k = (*k)->acceptMutator(*visitor);
     48                        *k = (*k)->acceptMutator(*this);
    4949
    5050                        if ( ! get_breakLabel().empty() ) {
     
    5757        }
    5858
    59         void MLEMutator::premutate( CompoundStmt *cmpndStmt ) {
    60                 visit_children = false;
    61                 bool labeledBlock = !(cmpndStmt->labels.empty());
     59        CompoundStmt* MLEMutator::mutate( CompoundStmt *cmpndStmt ) {
     60                bool labeledBlock = !(cmpndStmt->get_labels().empty());
    6261                if ( labeledBlock ) {
    6362                        Label brkLabel = generator->newLabel("blockBreak", cmpndStmt);
     
    6665
    6766                // a child statement may set the break label - if they do, attach it to the next statement
    68                 std::list< Statement * > &kids = cmpndStmt->kids;
     67                std::list< Statement * > &kids = cmpndStmt->get_kids();
    6968                fixBlock( kids );
    7069
     
    7675                        enclosingControlStructures.pop_back();
    7776                } // if
    78         }
    79 
     77
     78                return cmpndStmt;
     79        }
     80
     81        template< typename LoopClass >
     82        Statement *MLEMutator::handleLoopStmt( LoopClass *loopStmt ) {
     83                // remember this as the most recent enclosing loop, then mutate the body of the loop -- this will determine
     84                // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested
     85                // loops
     86                Label brkLabel = generator->newLabel("loopBreak", loopStmt);
     87                Label contLabel = generator->newLabel("loopContinue", loopStmt);
     88                enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
     89                loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) );
     90
     91                assert( ! enclosingControlStructures.empty() );
     92                Entry &e = enclosingControlStructures.back();
     93                // sanity check that the enclosing loops have been popped correctly
     94                assert ( e == loopStmt );
     95
     96                // this will take the necessary steps to add definitions of the previous two labels, if they are used.
     97                loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) );
     98                enclosingControlStructures.pop_back();
     99
     100                return loopStmt;
     101        }
     102
     103        Statement *MLEMutator::mutate( CaseStmt *caseStmt ) {
     104                caseStmt->set_condition( maybeMutate( caseStmt->get_condition(), *this ) );
     105                fixBlock( caseStmt->get_statements() );
     106
     107                return caseStmt;
     108        }
     109
     110        template< typename IfClass >
     111        Statement *MLEMutator::handleIfStmt( IfClass *ifStmt ) {
     112                // generate a label for breaking out of a labeled if
     113                bool labeledBlock = !(ifStmt->get_labels().empty());
     114                if ( labeledBlock ) {
     115                        Label brkLabel = generator->newLabel("blockBreak", ifStmt);
     116                        enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
     117                } // if
     118
     119                Parent::mutate( ifStmt );
     120
     121                if ( labeledBlock ) {
     122                        if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
     123                                set_breakLabel( enclosingControlStructures.back().useBreakExit() );
     124                        } // if
     125                        enclosingControlStructures.pop_back();
     126                } // if
     127                return ifStmt;
     128        }
     129
     130        template< typename SwitchClass >
     131        Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) {
     132                // generate a label for breaking out of a labeled switch
     133                Label brkLabel = generator->newLabel("switchBreak", switchStmt);
     134                enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
     135                mutateAll( switchStmt->get_statements(), *this );
     136
     137                Entry &e = enclosingControlStructures.back();
     138                assert ( e == switchStmt );
     139
     140                // only generate break label if labeled break is used
     141                if ( e.isBreakUsed() ) {
     142                        // for the purposes of keeping switch statements uniform (i.e. all statements that are direct children of a
     143                        // switch should be CastStmts), append the exit label + break to the last case statement; create a default
     144                        // case if there are no cases
     145                        std::list< Statement * > &statements = switchStmt->get_statements();
     146                        if ( statements.empty() ) {
     147                                statements.push_back( CaseStmt::makeDefault() );
     148                        } // if
     149
     150                        if ( CaseStmt * c = dynamic_cast< CaseStmt * >( statements.back() ) ) {
     151                                Statement * stmt = new BranchStmt( Label("brkLabel"), BranchStmt::Break );
     152                                stmt->labels.push_back( brkLabel );
     153                                c->get_statements().push_back( stmt );
     154                        } else assert(0); // as of this point, all statements of a switch are still CaseStmts
     155                } // if
     156
     157                assert ( enclosingControlStructures.back() == switchStmt );
     158                enclosingControlStructures.pop_back();
     159                return switchStmt;
     160        }
    80161
    81162        void addUnused( Statement * stmt, const Label & originalTarget ) {
     
    98179
    99180
    100         Statement *MLEMutator::postmutate( BranchStmt *branchStmt ) throw ( SemanticError ) {
    101                 std::string originalTarget = branchStmt->originalTarget;
     181        Statement *MLEMutator::mutate( BranchStmt *branchStmt ) throw ( SemanticError ) {
     182                std::string originalTarget = branchStmt->get_originalTarget();
    102183
    103184                std::list< Entry >::reverse_iterator targetEntry;
     
    134215                // branch error checks, get the appropriate label name and create a goto
    135216                Label exitLabel;
    136                 switch ( branchStmt->type ) {
     217                switch ( branchStmt->get_type() ) {
    137218                  case BranchStmt::Break:
    138219                                assert( targetEntry->useBreakExit() != "");
     
    148229
    149230                // add unused attribute to label to silence warnings
    150                 addUnused( targetEntry->get_controlStructure(), branchStmt->originalTarget );
     231                addUnused( targetEntry->get_controlStructure(), branchStmt->get_originalTarget() );
    151232
    152233                // transform break/continue statements into goto to simplify later handling of branches
     
    179260        }
    180261
    181         template< typename LoopClass >
    182         void MLEMutator::prehandleLoopStmt( LoopClass * loopStmt ) {
    183                 // remember this as the most recent enclosing loop, then mutate the body of the loop -- this will determine
    184                 // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested
    185                 // loops
    186                 Label brkLabel = generator->newLabel("loopBreak", loopStmt);
    187                 Label contLabel = generator->newLabel("loopContinue", loopStmt);
    188                 enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
    189         }
    190 
    191         template< typename LoopClass >
    192         Statement * MLEMutator::posthandleLoopStmt( LoopClass * loopStmt ) {
    193                 assert( ! enclosingControlStructures.empty() );
    194                 Entry &e = enclosingControlStructures.back();
    195                 // sanity check that the enclosing loops have been popped correctly
    196                 assert ( e == loopStmt );
    197 
    198                 // this will take the necessary steps to add definitions of the previous two labels, if they are used.
    199                 loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) );
    200                 enclosingControlStructures.pop_back();
    201                 return loopStmt;
    202         }
    203 
    204         void MLEMutator::premutate( WhileStmt * whileStmt ) {
    205                 return prehandleLoopStmt( whileStmt );
    206         }
    207 
    208         void MLEMutator::premutate( ForStmt * forStmt ) {
    209                 return prehandleLoopStmt( forStmt );
    210         }
    211 
    212         Statement * MLEMutator::postmutate( WhileStmt * whileStmt ) {
    213                 return posthandleLoopStmt( whileStmt );
    214         }
    215 
    216         Statement * MLEMutator::postmutate( ForStmt * forStmt ) {
    217                 return posthandleLoopStmt( forStmt );
    218         }
    219 
    220         void MLEMutator::premutate( IfStmt * ifStmt ) {
    221                 // generate a label for breaking out of a labeled if
    222                 bool labeledBlock = !(ifStmt->get_labels().empty());
    223                 if ( labeledBlock ) {
    224                         Label brkLabel = generator->newLabel("blockBreak", ifStmt);
    225                         enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
    226                 } // if
    227         }
    228 
    229         Statement * MLEMutator::postmutate( IfStmt * ifStmt ) {
    230                 bool labeledBlock = !(ifStmt->get_labels().empty());
    231                 if ( labeledBlock ) {
    232                         if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
    233                                 set_breakLabel( enclosingControlStructures.back().useBreakExit() );
    234                         } // if
    235                         enclosingControlStructures.pop_back();
    236                 } // if
    237                 return ifStmt;
    238         }
    239 
    240         void MLEMutator::premutate( CaseStmt *caseStmt ) {
    241                 visit_children = false;
    242                 caseStmt->condition = maybeMutate( caseStmt->condition, *visitor );
    243                 fixBlock( caseStmt->stmts );
    244         }
    245 
    246         void MLEMutator::premutate( SwitchStmt *switchStmt ) {
    247                 // generate a label for breaking out of a labeled switch
    248                 Label brkLabel = generator->newLabel("switchBreak", switchStmt);
    249                 enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
    250         }
    251 
    252         Statement * MLEMutator::postmutate( SwitchStmt * switchStmt ) {
    253                 Entry &e = enclosingControlStructures.back();
    254                 assert ( e == switchStmt );
    255 
    256                 // only generate break label if labeled break is used
    257                 if ( e.isBreakUsed() ) {
    258                         // for the purposes of keeping switch statements uniform (i.e. all statements that are direct children of a
    259                         // switch should be CastStmts), append the exit label + break to the last case statement; create a default
    260                         // case if there are no cases
    261                         std::list< Statement * > &statements = switchStmt->statements;
    262                         if ( statements.empty() ) {
    263                                 statements.push_back( CaseStmt::makeDefault() );
    264                         } // if
    265 
    266                         if ( CaseStmt * c = dynamic_cast< CaseStmt * >( statements.back() ) ) {
    267                                 Statement * stmt = new BranchStmt( Label("brkLabel"), BranchStmt::Break );
    268                                 stmt->labels.push_back( e.useBreakExit() );
    269                                 c->stmts.push_back( stmt );
    270                         } else assert(0); // as of this point, all statements of a switch are still CaseStmts
    271                 } // if
    272 
    273                 assert ( enclosingControlStructures.back() == switchStmt );
    274                 enclosingControlStructures.pop_back();
    275                 return switchStmt;
     262        Statement *MLEMutator::mutate( WhileStmt *whileStmt ) {
     263                return handleLoopStmt( whileStmt );
     264        }
     265
     266        Statement *MLEMutator::mutate( ForStmt *forStmt ) {
     267                return handleLoopStmt( forStmt );
     268        }
     269
     270        Statement *MLEMutator::mutate( IfStmt *ifStmt ) {
     271                return handleIfStmt( ifStmt );
     272        }
     273
     274        Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) {
     275                return handleSwitchStmt( switchStmt );
    276276        }
    277277} // namespace ControlStruct
Note: See TracChangeset for help on using the changeset viewer.