Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MLEMutator.cc

    reb3261f r843054c2  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Thu Jun 04 15:12:33 2015
    13 // Update Count     : 173
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue May 19 15:32:26 2015
     13// Update Count     : 2
    1414//
    1515
     
    1919#include "MLEMutator.h"
    2020#include "SynTree/Statement.h"
    21 #include "SynTree/Expression.h"
    2221
    2322namespace ControlStruct {
     
    2726        }
    2827
    29         // break labels have to come after the statement they break out of,
    30         // so mutate a statement, then if they inform us through the breakLabel field
    31         // tha they need a place to jump to on a break statement, add the break label
    32         // to the body of statements
    33         void MLEMutator::fixBlock( std::list< Statement * > &kids ) {
     28        CompoundStmt* MLEMutator::mutate( CompoundStmt *cmpndStmt ) {
     29                bool labeledBlock = false;
     30                if ( !((cmpndStmt->get_labels()).empty()) ) {
     31                        labeledBlock = true;
     32                        enclosingBlocks.push_back( Entry( cmpndStmt ) );
     33                } // if
     34
     35                std::list< Statement * > &kids = cmpndStmt->get_kids();
    3436                for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) {
    3537                        *k = (*k)->acceptMutator(*this);
    3638
    3739                        if ( ! get_breakLabel().empty() ) {
    38                                 std::list< Statement * >::iterator next = k+1;
     40                                std::list< Statement * >::iterator next = k; next++;
    3941                                if ( next == kids.end() ) {
    4042                                        std::list<Label> ls; ls.push_back( get_breakLabel() );
    4143                                        kids.push_back( new NullStmt( ls ) );
    42                                 } else {
     44                                } else
    4345                                        (*next)->get_labels().push_back( get_breakLabel() );
    44                                 }
    4546
    4647                                set_breakLabel("");
    4748                        } // if
    4849                } // for
    49         }
    50 
    51         CompoundStmt* MLEMutator::mutate( CompoundStmt *cmpndStmt ) {
    52                 bool labeledBlock = !(cmpndStmt->get_labels().empty());
    53                 if ( labeledBlock ) {
    54                         Label brkLabel = generator->newLabel("blockBreak");
    55                         enclosingBlocks.push_back( Entry( cmpndStmt, brkLabel ) );
    56                 } // if
    57 
    58                 // a child statement may set the break label
    59                 // - if they do, attach it to the next statement
    60                 std::list< Statement * > &kids = cmpndStmt->get_kids();
    61                 fixBlock( kids );
    6250
    6351                if ( labeledBlock ) {
    6452                        assert( ! enclosingBlocks.empty() );
    65                         if ( ! enclosingBlocks.back().useBreakExit().empty() ) {
    66                                 set_breakLabel( enclosingBlocks.back().useBreakExit() );
    67                         }
     53                        if ( ! enclosingBlocks.back().get_breakExit().empty() )
     54                                set_breakLabel( enclosingBlocks.back().get_breakExit() );
    6855                        enclosingBlocks.pop_back();
    6956                } // if
    7057
     58                //mutateAll( cmpndStmt->get_kids(), *this );
    7159                return cmpndStmt;
    7260        }
    7361
    74         template< typename LoopClass >
    75         Statement *MLEMutator::handleLoopStmt( LoopClass *loopStmt ) {
    76                 // remember this as the most recent enclosing loop, then mutate
    77                 // the body of the loop -- this will determine whether brkLabel
    78                 // and contLabel are used with branch statements
    79                 // and will recursively do the same to nested loops
    80                 Label brkLabel = generator->newLabel("loopBreak");
    81                 Label contLabel = generator->newLabel("loopContinue");
    82                 enclosingLoops.push_back( Entry( loopStmt, brkLabel, contLabel ) );
    83                 loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) );
    84 
    85                 // sanity check that the enclosing loops have been popped correctly
     62        Statement *MLEMutator::mutate( WhileStmt *whileStmt ) {
     63                enclosingLoops.push_back( Entry( whileStmt ) );
     64                whileStmt->set_body ( whileStmt->get_body()->acceptMutator( *this ) );
     65
    8666                Entry &e = enclosingLoops.back();
    87                 assert ( e == loopStmt );
    88 
    89                 // this will take the necessary steps to add definitions of the previous
    90                 // two labels, if they are used.
    91                 loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) );
     67                assert ( e == whileStmt );
     68                whileStmt->set_body( mutateLoop( whileStmt->get_body(), e ) );
    9269                enclosingLoops.pop_back();
    9370
    94                 return loopStmt;
    95         }
    96 
    97         Statement *MLEMutator::mutate( CaseStmt *caseStmt ) {
    98                 caseStmt->set_condition( maybeMutate( caseStmt->get_condition(), *this ) );
    99                 fixBlock( caseStmt->get_statements() );
    100 
    101                 return caseStmt;
    102         }
    103 
    104         template< typename SwitchClass >
    105         Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) {
    106                 // generate a label for breaking out of a labeled switch
    107                 Label brkLabel = generator->newLabel("switchBreak");
    108                 enclosingSwitches.push_back( Entry(switchStmt, brkLabel) );
    109                 mutateAll( switchStmt->get_branches(), *this );
    110 
    111                 Entry &e = enclosingSwitches.back();
    112                 assert ( e == switchStmt );
    113 
    114                 // only generate break label if labeled break is used
    115                 if (e.isBreakUsed()) {
    116                         // for the purposes of keeping switch statements uniform (i.e. all statements that are
    117                         // direct children of a switch should be CastStmts), append the exit label + break to the
    118                         // last case statement; create a default case if there are no cases
    119                         std::list< Statement * > &branches = switchStmt->get_branches();
    120                         if ( branches.empty() ) {
    121                                 branches.push_back( CaseStmt::makeDefault() );
    122                         }
    123 
    124                         if ( CaseStmt * c = dynamic_cast< CaseStmt * >( branches.back() ) ) {
    125                                 std::list<Label> temp; temp.push_back( brkLabel );
    126                                 c->get_statements().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
    127                         } else assert(0); // as of this point, all branches of a switch are still CaseStmts
    128                 }
    129 
    130                 assert ( enclosingSwitches.back() == switchStmt );
    131                 enclosingSwitches.pop_back();
    132                 return switchStmt;
     71                return whileStmt;
     72        }
     73
     74        Statement *MLEMutator::mutate( ForStmt *forStmt ) {
     75                enclosingLoops.push_back( Entry( forStmt ) );
     76                maybeMutate( forStmt->get_body(), *this );
     77
     78                Entry &e = enclosingLoops.back();
     79                assert ( e == forStmt );
     80                forStmt->set_body( mutateLoop( forStmt->get_body(), e ) );
     81                enclosingLoops.pop_back();
     82
     83                return forStmt;
    13384        }
    13485
    13586        Statement *MLEMutator::mutate( BranchStmt *branchStmt ) throw ( SemanticError ) {
    136                 std::string originalTarget = branchStmt->get_originalTarget();
    137 
    13887                if ( branchStmt->get_type() == BranchStmt::Goto )
    13988                        return branchStmt;
    14089
    14190                // test if continue target is a loop
    142                 if ( branchStmt->get_type() == BranchStmt::Continue) {
    143                         if ( enclosingLoops.empty() ) {
    144                                 throw SemanticError( "'continue' outside a loop" );
    145                         } else if ( std::find( enclosingLoops.begin(), enclosingLoops.end(), (*targetTable)[branchStmt->get_target()] ) == enclosingLoops.end() ) {
    146                                 throw SemanticError( "'continue' target label must be an enclosing loop: " + originalTarget );
    147                         }
    148                 }
     91                if ( branchStmt->get_type() == BranchStmt::Continue && enclosingLoops.empty() )
     92                        throw SemanticError( "'continue' outside a loop" );
    14993
    15094                if ( branchStmt->get_type() == BranchStmt::Break && (enclosingLoops.empty() && enclosingSwitches.empty() && enclosingBlocks.empty() ) )
     
    15498
    15599                if ( targetTable->find( branchStmt->get_target() ) == targetTable->end() )
    156                         throw SemanticError("The label defined in the exit loop statement does not exist: " + originalTarget );  // shouldn't happen (since that's already checked)
     100                        throw SemanticError("The label defined in the exit loop statement does not exist." );  // shouldn't happen (since that's already checked)
    157101
    158102                std::list< Entry >::iterator check;
     
    162106                                // neither in loop nor in block, checking if in switch/choose
    163107                                if ( (check = std::find( enclosingSwitches.begin(), enclosingSwitches.end(), (*targetTable)[branchStmt->get_target()] )) == enclosingSwitches.end() )
    164                                         throw SemanticError("The target specified in the exit loop statement does not correspond to an enclosing control structure: " + originalTarget );
    165 
    166                 // what about exiting innermost block or switch???
     108                                        throw SemanticError("The target specified in the exit loop statement does not correspond to an enclosing loop.");
     109
    167110                if ( enclosingLoops.back() == (*check) )
    168111                        return branchStmt;                              // exit the innermost loop (labels unnecessary)
    169112
    170                 // branch error checks, get the appropriate label name and create a goto
    171                 Label exitLabel;
     113                Label newLabel;
    172114                switch ( branchStmt->get_type() ) {
    173115                  case BranchStmt::Break:
    174                                 assert( check->useBreakExit() != "");
    175                                 exitLabel = check->useBreakExit();
    176                                 break;
     116                        if ( check->get_breakExit() != "" )
     117                                newLabel = check->get_breakExit();
     118                        else {
     119                                newLabel = generator->newLabel();
     120                                check->set_breakExit( newLabel );
     121                        } // if
     122                        break;
    177123                  case BranchStmt::Continue:
    178                                 assert( check->useContExit() != "");
    179                                 exitLabel = check->useContExit();
    180                                 break;
     124                        if ( check->get_contExit() != "" )
     125                                newLabel = check->get_contExit();
     126                        else {
     127                                newLabel = generator->newLabel();
     128                                check->set_contExit( newLabel );
     129                        } // if
     130                        break;
    181131                  default:
    182                                 assert(0);                                      // shouldn't be here
     132                        return 0;                                       // shouldn't be here
    183133                } // switch
    184134
    185                 return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
     135                return new BranchStmt( std::list<Label>(), newLabel, BranchStmt::Goto );
     136        }
     137
     138
     139        Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) {
     140                Label brkLabel = generator->newLabel();
     141                enclosingSwitches.push_back( Entry(switchStmt, "", brkLabel) );
     142                mutateAll( switchStmt->get_branches(), *this ); {
     143                        // check if this is necessary (if there is a break to this point, otherwise do not generate
     144                        std::list<Label> temp; temp.push_back( brkLabel );
     145                        switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
     146                }
     147                assert ( enclosingSwitches.back() == switchStmt );
     148                enclosingSwitches.pop_back();
     149                return switchStmt;
     150        }
     151
     152        Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) {
     153                Label brkLabel = generator->newLabel();
     154                enclosingSwitches.push_back( Entry(switchStmt,"", brkLabel) );
     155                mutateAll( switchStmt->get_branches(), *this ); {
     156                        // check if this is necessary (if there is a break to this point, otherwise do not generate
     157                        std::list<Label> temp; temp.push_back( brkLabel );
     158                        switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
     159                }
     160                assert ( enclosingSwitches.back() == switchStmt );
     161                enclosingSwitches.pop_back();
     162                return switchStmt;
    186163        }
    187164
    188165        Statement *MLEMutator::mutateLoop( Statement *bodyLoop, Entry &e ) {
    189                 // ensure loop body is a block
    190166                CompoundStmt *newBody;
    191167                if ( ! (newBody = dynamic_cast<CompoundStmt *>( bodyLoop )) ) {
     
    194170                } // if
    195171
    196                 // only generate these when needed
    197 
    198                 if ( e.isContUsed() ) {
    199                         // continue label goes in the body as the last statement
    200                         std::list< Label > labels; labels.push_back( e.useContExit() );
    201                         newBody->get_kids().push_back( new NullStmt( labels ) );                       
    202                 }
    203 
    204                 if ( e.isBreakUsed() ) {
    205                         // break label goes after the loop -- it'll get set by the
    206                         // outer mutator if we do this
    207                         set_breakLabel( e.useBreakExit() );                     
    208                 }
     172                Label endLabel = e.get_contExit();
     173
     174                if ( e.get_breakExit() != "" ) {
     175                        if ( endLabel == "" ) endLabel = generator->newLabel();
     176                        // check for whether this label is used or not, so as to not generate extraneous gotos
     177                        if (e.breakExitUsed)
     178                                newBody->get_kids().push_back( new BranchStmt( std::list< Label >(), endLabel, BranchStmt::Goto ) );
     179                        // xxx
     180                        //std::list< Label > ls; ls.push_back( e.get_breakExit() );
     181                        set_breakLabel( e.get_breakExit() );
     182                        //newBody->get_kids().push_back( new BranchStmt( ls, "", BranchStmt::Break ) );
     183                } // if
     184
     185                if ( e.get_breakExit() != "" || e.get_contExit() != "" ) {
     186                        if (dynamic_cast< NullStmt *>( newBody->get_kids().back() ))
     187                                newBody->get_kids().back()->get_labels().push_back( endLabel );
     188                        else {
     189                                std::list < Label > ls; ls.push_back( endLabel );
     190                                newBody->get_kids().push_back( new NullStmt( ls ) );
     191                        } // if
     192                } // if
    209193
    210194                return newBody;
    211195        }
    212196
    213         Statement *MLEMutator::mutate( WhileStmt *whileStmt ) {
    214                 return handleLoopStmt( whileStmt );
    215         }
    216 
    217         Statement *MLEMutator::mutate( ForStmt *forStmt ) {
    218                 return handleLoopStmt( forStmt );
    219         }
    220 
    221         Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) {
    222                 return handleSwitchStmt( switchStmt );
    223         }
    224 
    225         Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) {
    226                 return handleSwitchStmt( switchStmt );         
    227         }
    228 
     197        //*** Entry's methods
     198        void MLEMutator::Entry::set_contExit( Label l ) {
     199                assert ( contExit == "" || contExit == l );
     200                contExit = l;
     201        }
     202
     203        void MLEMutator::Entry::set_breakExit( Label l ) {
     204                assert ( breakExit == "" || breakExit == l );
     205                breakExit = l;
     206        }
    229207} // namespace ControlStruct
    230208
Note: See TracChangeset for help on using the changeset viewer.