"Fossies" - the Fresh Open Source Software Archive

Member "ragel-6.10/ragel/rbxgoto.cpp" (24 Mar 2017, 22067 Bytes) of package /linux/misc/ragel-6.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rbxgoto.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 6.9_vs_6.10.

    1 /*
    2  *  Copyright 2007 Victor Hugo Borja <vic@rubyforge.org>
    3  *            2006-2007 Adrian Thurston <thurston@complang.org>
    4  */
    5 
    6 /*  This file is part of Ragel.
    7  *
    8  *  Ragel is free software; you can redistribute it and/or modify
    9  *  it under the terms of the GNU General Public License as published by
   10  *  the Free Software Foundation; either version 2 of the License, or
   11  *  (at your option) any later version.
   12  * 
   13  *  Ragel is distributed in the hope that it will be useful,
   14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  *  GNU General Public License for more details.
   17  * 
   18  *  You should have received a copy of the GNU General Public License
   19  *  along with Ragel; if not, write to the Free Software
   20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
   21  */
   22 
   23 #include <stdio.h>
   24 #include <string>
   25 
   26 #include "rbxgoto.h"
   27 #include "ragel.h"
   28 #include "redfsm.h"
   29 #include "bstmap.h"
   30 #include "gendata.h"
   31 
   32 using std::ostream;
   33 using std::string;
   34 
   35 inline string label(string a, int i)
   36 {
   37     return a + itoa(i);
   38 }
   39 
   40 ostream &RbxGotoCodeGen::rbxLabel(ostream &out, string label)
   41 {
   42     out << "Rubinius.asm { @labels[:_" << FSM_NAME() << "_" << label << "].set! }\n";
   43     return out;
   44 }
   45 
   46 ostream &RbxGotoCodeGen::rbxGoto(ostream &out, string label)
   47 {
   48     out << "Rubinius.asm { goto @labels[:_" << FSM_NAME() << "_" << label << "] }\n";
   49     return out;
   50 }
   51 
   52 /* Emit the goto to take for a given transition. */
   53 std::ostream &RbxGotoCodeGen::TRANS_GOTO( RedTransAp *trans, int level )
   54 {
   55     out << TABS(level);
   56     return rbxGoto(out, label("tr",trans->id));
   57 }
   58 
   59 std::ostream &RbxGotoCodeGen::TO_STATE_ACTION_SWITCH()
   60 {
   61     /* Walk the list of functions, printing the cases. */
   62     for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
   63         /* Write out referenced actions. */
   64         if ( act->numToStateRefs > 0 ) {
   65             /* Write the case label, the action and the case break. */
   66             out << "\twhen " << act->actionId << " then\n";
   67             ACTION( out, act, 0, false );
   68         }
   69     }
   70 
   71     genLineDirective( out );
   72     return out;
   73 }
   74 
   75 std::ostream &RbxGotoCodeGen::FROM_STATE_ACTION_SWITCH()
   76 {
   77     /* Walk the list of functions, printing the cases. */
   78     for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
   79         /* Write out referenced actions. */
   80         if ( act->numFromStateRefs > 0 ) {
   81             /* Write the case label, the action and the case break. */
   82             out << "\twhen " << act->actionId << " then\n";
   83             ACTION( out, act, 0, false );
   84         }
   85     }
   86 
   87     genLineDirective( out );
   88     return out;
   89 }
   90 
   91 std::ostream &RbxGotoCodeGen::EOF_ACTION_SWITCH()
   92 {
   93     /* Walk the list of functions, printing the cases. */
   94     for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
   95         /* Write out referenced actions. */
   96         if ( act->numEofRefs > 0 ) {
   97             /* Write the case label, the action and the case break. */
   98             out << "\twhen " << act->actionId << " then\n";
   99             ACTION( out, act, 0, true );
  100         }
  101     }
  102 
  103     genLineDirective( out );
  104     return out;
  105 }
  106 
  107 std::ostream &RbxGotoCodeGen::ACTION_SWITCH()
  108 {
  109     /* Walk the list of functions, printing the cases. */
  110     for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  111         /* Write out referenced actions. */
  112         if ( act->numTransRefs > 0 ) {
  113             /* Write the case label, the action and the case break. */
  114             out << "\twhen " << act->actionId << " then\n";
  115             ACTION( out, act, 0, false );
  116         }
  117     }
  118 
  119     genLineDirective( out );
  120     return out;
  121 }
  122 
  123 void RbxGotoCodeGen::GOTO_HEADER( RedStateAp *state )
  124 {
  125     /* Label the state. */
  126     out << "when " << state->id << " then\n";
  127 }
  128 
  129 
  130 void RbxGotoCodeGen::emitSingleSwitch( RedStateAp *state )
  131 {
  132     /* Load up the singles. */
  133     int numSingles = state->outSingle.length();
  134     RedTransEl *data = state->outSingle.data;
  135 
  136     if ( numSingles == 1 ) {
  137         /* If there is a single single key then write it out as an if. */
  138         out << "\tif " << GET_WIDE_KEY(state) << " == " << 
  139             KEY(data[0].lowKey) << " \n\t\t"; 
  140 
  141         /* Virtual function for writing the target of the transition. */
  142         TRANS_GOTO(data[0].value, 0) << "\n";
  143 
  144         out << "end\n";
  145     }
  146     else if ( numSingles > 1 ) {
  147         /* Write out single keys in a switch if there is more than one. */
  148         out << "\tcase  " << GET_WIDE_KEY(state) << "\n";
  149 
  150         /* Write out the single indicies. */
  151         for ( int j = 0; j < numSingles; j++ ) {
  152             out << "\t\twhen " << KEY(data[j].lowKey) << " then\n";
  153             TRANS_GOTO(data[j].value, 0) << "\n";
  154         }
  155         
  156         /* Close off the transition switch. */
  157         out << "\tend\n";
  158     }
  159 }
  160 
  161 void RbxGotoCodeGen::emitRangeBSearch( RedStateAp *state, int level, int low, int high )
  162 {
  163     /* Get the mid position, staying on the lower end of the range. */
  164     int mid = (low + high) >> 1;
  165     RedTransEl *data = state->outRange.data;
  166 
  167     /* Determine if we need to look higher or lower. */
  168     bool anyLower = mid > low;
  169     bool anyHigher = mid < high;
  170 
  171     /* Determine if the keys at mid are the limits of the alphabet. */
  172     bool limitLow = data[mid].lowKey == keyOps->minKey;
  173     bool limitHigh = data[mid].highKey == keyOps->maxKey;
  174 
  175     if ( anyLower && anyHigher ) {
  176         /* Can go lower and higher than mid. */
  177         out << TABS(level) << "if " << GET_WIDE_KEY(state) << " < " << 
  178             KEY(data[mid].lowKey) << " \n";
  179         emitRangeBSearch( state, level+1, low, mid-1 );
  180         out << TABS(level) << "elsif " << GET_WIDE_KEY(state) << " > " << 
  181             KEY(data[mid].highKey) << " \n";
  182         emitRangeBSearch( state, level+1, mid+1, high );
  183         out << TABS(level) << "else\n";
  184         TRANS_GOTO(data[mid].value, level+1) << "\n";
  185         out << TABS(level) << "end\n";
  186     }
  187     else if ( anyLower && !anyHigher ) {
  188         /* Can go lower than mid but not higher. */
  189         out << TABS(level) << "if " << GET_WIDE_KEY(state) << " < " << 
  190             KEY(data[mid].lowKey) << " then\n";
  191         emitRangeBSearch( state, level+1, low, mid-1 );
  192 
  193         /* if the higher is the highest in the alphabet then there is no
  194          * sense testing it. */
  195         if ( limitHigh ) {
  196             out << TABS(level) << "else\n";
  197             TRANS_GOTO(data[mid].value, level+1) << "\n";
  198         }
  199         else {
  200             out << TABS(level) << "elsif" << GET_WIDE_KEY(state) << " <= " << 
  201                 KEY(data[mid].highKey) << " )\n";
  202             TRANS_GOTO(data[mid].value, level+1) << "\n";
  203         }
  204         out << TABS(level) << "end\n";
  205     }
  206     else if ( !anyLower && anyHigher ) {
  207         /* Can go higher than mid but not lower. */
  208         out << TABS(level) << "if " << GET_WIDE_KEY(state) << " > " << 
  209             KEY(data[mid].highKey) << " \n";
  210         emitRangeBSearch( state, level+1, mid+1, high );
  211 
  212         /* If the lower end is the lowest in the alphabet then there is no
  213          * sense testing it. */
  214         if ( limitLow ) {
  215             out << TABS(level) << "else\n";
  216             TRANS_GOTO(data[mid].value, level+1) << "\n";
  217         }
  218         else {
  219             out << TABS(level) << "elsif " << GET_WIDE_KEY(state) << " >= " << 
  220                 KEY(data[mid].lowKey) << " then\n";
  221             TRANS_GOTO(data[mid].value, level+1) << "\n";
  222         }
  223         out << TABS(level) << "end\n";
  224     }
  225     else {
  226         /* Cannot go higher or lower than mid. It's mid or bust. What
  227          * tests to do depends on limits of alphabet. */
  228         if ( !limitLow && !limitHigh ) {
  229             out << TABS(level) << "if " << KEY(data[mid].lowKey) << " <= " << 
  230                 GET_WIDE_KEY(state) << " && " << GET_WIDE_KEY(state) << " <= " << 
  231                 KEY(data[mid].highKey) << " \n";
  232             TRANS_GOTO(data[mid].value, level+1) << "\n";
  233             out << TABS(level) << "end\n";
  234         }
  235         else if ( limitLow && !limitHigh ) {
  236             out << TABS(level) << "if " << GET_WIDE_KEY(state) << " <= " << 
  237                 KEY(data[mid].highKey) << " \n";
  238             TRANS_GOTO(data[mid].value, level+1) << "\n";
  239             out << TABS(level) << "end\n";
  240         }
  241         else if ( !limitLow && limitHigh ) {
  242             out << TABS(level) << "if " << KEY(data[mid].lowKey) << " <= " << 
  243                 GET_WIDE_KEY(state) << " \n";
  244             TRANS_GOTO(data[mid].value, level+1) << "\n";
  245             out << TABS(level) << "end\n";
  246         }
  247         else {
  248             /* Both high and low are at the limit. No tests to do. */
  249             TRANS_GOTO(data[mid].value, level+1) << "\n";
  250         }
  251     }
  252 }
  253 
  254 void RbxGotoCodeGen::STATE_GOTO_ERROR()
  255 {
  256     /* Label the state and bail immediately. */
  257     outLabelUsed = true;
  258     RedStateAp *state = redFsm->errState;
  259     out << "when " << state->id << " then\n";
  260     rbxGoto(out << "    ", "_out") << "\n";
  261 }
  262 
  263 void RbxGotoCodeGen::COND_TRANSLATE( GenStateCond *stateCond, int level )
  264 {
  265     GenCondSpace *condSpace = stateCond->condSpace;
  266     out << TABS(level) << "_widec = " <<
  267         KEY(condSpace->baseKey) << " + (" << GET_KEY() << 
  268         " - " << KEY(keyOps->minKey) << ");\n";
  269 
  270     for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
  271         out << TABS(level) << "if ";
  272         CONDITION( out, *csi );
  273         Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
  274         out << "\n _widec += " << condValOffset << ";\n end";
  275     }
  276 }
  277 
  278 void RbxGotoCodeGen::emitCondBSearch( RedStateAp *state, int level, int low, int high )
  279 {
  280     /* Get the mid position, staying on the lower end of the range. */
  281     int mid = (low + high) >> 1;
  282     GenStateCond **data = state->stateCondVect.data;
  283 
  284     /* Determine if we need to look higher or lower. */
  285     bool anyLower = mid > low;
  286     bool anyHigher = mid < high;
  287 
  288     /* Determine if the keys at mid are the limits of the alphabet. */
  289     bool limitLow = data[mid]->lowKey == keyOps->minKey;
  290     bool limitHigh = data[mid]->highKey == keyOps->maxKey;
  291 
  292     if ( anyLower && anyHigher ) {
  293         /* Can go lower and higher than mid. */
  294         out << TABS(level) << "if " << GET_KEY() << " < " << 
  295             KEY(data[mid]->lowKey) << " \n";
  296         emitCondBSearch( state, level+1, low, mid-1 );
  297         out << TABS(level) << "elsif " << GET_KEY() << " > " << 
  298             KEY(data[mid]->highKey) << " \n";
  299         emitCondBSearch( state, level+1, mid+1, high );
  300         out << TABS(level) << "else\n";
  301         COND_TRANSLATE(data[mid], level+1);
  302         out << TABS(level) << "end\n";
  303     }
  304     else if ( anyLower && !anyHigher ) {
  305         /* Can go lower than mid but not higher. */
  306         out << TABS(level) << "if " << GET_KEY() << " < " << 
  307             KEY(data[mid]->lowKey) << " \n";
  308         emitCondBSearch( state, level+1, low, mid-1 );
  309 
  310         /* if the higher is the highest in the alphabet then there is no
  311          * sense testing it. */
  312         if ( limitHigh ) {
  313             out << TABS(level) << "else\n";
  314             COND_TRANSLATE(data[mid], level+1);
  315         }
  316         else {
  317             out << TABS(level) << "elsif " << GET_KEY() << " <= " << 
  318                 KEY(data[mid]->highKey) << " then\n";
  319             COND_TRANSLATE(data[mid], level+1);
  320         }
  321         out << TABS(level) << "end\n";
  322 
  323     }
  324     else if ( !anyLower && anyHigher ) {
  325         /* Can go higher than mid but not lower. */
  326         out << TABS(level) << "if " << GET_KEY() << " > " << 
  327             KEY(data[mid]->highKey) << " \n";
  328         emitCondBSearch( state, level+1, mid+1, high );
  329 
  330         /* If the lower end is the lowest in the alphabet then there is no
  331          * sense testing it. */
  332         if ( limitLow ) {
  333             out << TABS(level) << "else\n";
  334             COND_TRANSLATE(data[mid], level+1);
  335         }
  336         else {
  337             out << TABS(level) << "elsif " << GET_KEY() << " >= " << 
  338                 KEY(data[mid]->lowKey) << " then\n";
  339             COND_TRANSLATE(data[mid], level+1);
  340         }
  341         out << TABS(level) << "end\n";
  342     }
  343     else {
  344         /* Cannot go higher or lower than mid. It's mid or bust. What
  345          * tests to do depends on limits of alphabet. */
  346         if ( !limitLow && !limitHigh ) {
  347             out << TABS(level) << "if " << KEY(data[mid]->lowKey) << " <= " << 
  348                 GET_KEY() << " && " << GET_KEY() << " <= " << 
  349                 KEY(data[mid]->highKey) << " then\n";
  350             COND_TRANSLATE(data[mid], level+1);
  351             out << TABS(level) << "end\n";
  352         }
  353         else if ( limitLow && !limitHigh ) {
  354             out << TABS(level) << "if " << GET_KEY() << " <= " << 
  355                 KEY(data[mid]->highKey) << " then\n";
  356             COND_TRANSLATE(data[mid], level+1);
  357             out << TABS(level) << "end\n";
  358         }
  359         else if ( !limitLow && limitHigh ) {
  360             out << TABS(level) << "if " << KEY(data[mid]->lowKey) << " <= " << 
  361                 GET_KEY() << " then\n";
  362             COND_TRANSLATE(data[mid], level+1);
  363             out << TABS(level) << "end\n";
  364         }
  365         else {
  366             /* Both high and low are at the limit. No tests to do. */
  367             COND_TRANSLATE(data[mid], level);
  368         }
  369     }
  370 }
  371 
  372 std::ostream &RbxGotoCodeGen::STATE_GOTOS()
  373 {
  374     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  375         if ( st == redFsm->errState )
  376             STATE_GOTO_ERROR();
  377         else {
  378             /* Writing code above state gotos. */
  379             GOTO_HEADER( st );
  380 
  381             if ( st->stateCondVect.length() > 0 ) {
  382                 out << "    _widec = " << GET_KEY() << ";\n";
  383                 emitCondBSearch( st, 1, 0, st->stateCondVect.length() - 1 );
  384             }
  385 
  386             /* Try singles. */
  387             if ( st->outSingle.length() > 0 )
  388                 emitSingleSwitch( st );
  389 
  390             /* Default case is to binary search for the ranges, if that fails then */
  391             if ( st->outRange.length() > 0 )
  392                 emitRangeBSearch( st, 1, 0, st->outRange.length() - 1 );
  393 
  394             /* Write the default transition. */
  395             TRANS_GOTO( st->defTrans, 1 ) << "\n";
  396         }
  397     }
  398     return out;
  399 }
  400 
  401 std::ostream &RbxGotoCodeGen::TRANSITIONS()
  402 {
  403     /* Emit any transitions that have functions and that go to 
  404      * this state. */
  405     for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
  406         /* Write the label for the transition so it can be jumped to. */
  407         rbxLabel(out << "   ", label("tr", trans->id)) << "\n";
  408 
  409         /* Destination state. */
  410         if ( trans->action != 0 && trans->action->anyCurStateRef() )
  411             out << "_ps = " << vCS() << "'n";
  412         out << vCS() << " = " << trans->targ->id << "\n";
  413 
  414         if ( trans->action != 0 ) {
  415             /* Write out the transition func. */
  416             rbxGoto(out, label("f", trans->action->actListId)) << "\n";
  417         }
  418         else {
  419             /* No code to execute, just loop around. */
  420             rbxGoto(out, "_again") << "\n";
  421         }
  422     }
  423     return out;
  424 }
  425 
  426 std::ostream &RbxGotoCodeGen::EXEC_FUNCS()
  427 {
  428     /* Make labels that set acts and jump to execFuncs. Loop func indicies. */
  429     for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) {
  430         if ( redAct->numTransRefs > 0 ) {
  431             rbxLabel(out, label("f", redAct->actListId)) << "\n" <<
  432                 "_acts = " << itoa( redAct->location+1 ) << "\n";
  433             rbxGoto(out, "execFuncs") << "\n";
  434         }
  435     }
  436 
  437     rbxLabel(out, "execFuncs") <<
  438         "\n"
  439         "   _nacts = " << A() << "[_acts]\n"
  440         "   _acts += 1\n"
  441         "   while ( _nacts > 0 ) \n"
  442         "       _nacts -= 1\n"
  443         "       _acts += 1\n"
  444         "       case ( "<< A() << "[_acts-1] ) \n";
  445     ACTION_SWITCH();
  446     out <<
  447         "       end\n"
  448         "   end \n";
  449     rbxGoto(out, "_again");
  450     return out;
  451 }
  452 
  453 int RbxGotoCodeGen::TO_STATE_ACTION( RedStateAp *state )
  454 {
  455     int act = 0;
  456     if ( state->toStateAction != 0 )
  457         act = state->toStateAction->location+1;
  458     return act;
  459 }
  460 
  461 int RbxGotoCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  462 {
  463     int act = 0;
  464     if ( state->fromStateAction != 0 )
  465         act = state->fromStateAction->location+1;
  466     return act;
  467 }
  468 
  469 int RbxGotoCodeGen::EOF_ACTION( RedStateAp *state )
  470 {
  471     int act = 0;
  472     if ( state->eofAction != 0 )
  473         act = state->eofAction->location+1;
  474     return act;
  475 }
  476 
  477 std::ostream &RbxGotoCodeGen::TO_STATE_ACTIONS()
  478 {
  479     /* Take one off for the psuedo start state. */
  480     int numStates = redFsm->stateList.length();
  481     unsigned int *vals = new unsigned int[numStates];
  482     memset( vals, 0, sizeof(unsigned int)*numStates );
  483 
  484     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
  485         vals[st->id] = TO_STATE_ACTION(st);
  486 
  487     out << "\t";
  488     for ( int st = 0; st < redFsm->nextStateId; st++ ) {
  489         /* Write any eof action. */
  490         out << vals[st];
  491         if ( st < numStates-1 ) {
  492             out << ", ";
  493             if ( (st+1) % IALL == 0 )
  494                 out << "\n\t";
  495         }
  496     }
  497     out << "\n";
  498     delete[] vals;
  499     return out;
  500 }
  501 
  502 std::ostream &RbxGotoCodeGen::FROM_STATE_ACTIONS()
  503 {
  504     /* Take one off for the psuedo start state. */
  505     int numStates = redFsm->stateList.length();
  506     unsigned int *vals = new unsigned int[numStates];
  507     memset( vals, 0, sizeof(unsigned int)*numStates );
  508 
  509     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
  510         vals[st->id] = FROM_STATE_ACTION(st);
  511 
  512     out << "\t";
  513     for ( int st = 0; st < redFsm->nextStateId; st++ ) {
  514         /* Write any eof action. */
  515         out << vals[st];
  516         if ( st < numStates-1 ) {
  517             out << ", ";
  518             if ( (st+1) % IALL == 0 )
  519                 out << "\n\t";
  520         }
  521     }
  522     out << "\n";
  523     delete[] vals;
  524     return out;
  525 }
  526 
  527 std::ostream &RbxGotoCodeGen::EOF_ACTIONS()
  528 {
  529     /* Take one off for the psuedo start state. */
  530     int numStates = redFsm->stateList.length();
  531     unsigned int *vals = new unsigned int[numStates];
  532     memset( vals, 0, sizeof(unsigned int)*numStates );
  533 
  534     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
  535         vals[st->id] = EOF_ACTION(st);
  536 
  537     out << "\t";
  538     for ( int st = 0; st < redFsm->nextStateId; st++ ) {
  539         /* Write any eof action. */
  540         out << vals[st];
  541         if ( st < numStates-1 ) {
  542             out << ", ";
  543             if ( (st+1) % IALL == 0 )
  544                 out << "\n\t";
  545         }
  546     }
  547     out << "\n";
  548     delete[] vals;
  549     return out;
  550 }
  551 
  552 std::ostream &RbxGotoCodeGen::FINISH_CASES()
  553 {
  554     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  555         /* States that are final and have an out action need a case. */
  556         if ( st->eofAction != 0 ) {
  557             /* Write the case label. */
  558             out << "\t\twhen " << st->id << " then\n";
  559 
  560             /* Write the goto func. */
  561             rbxGoto(out, label("f", st->eofAction->actListId)) << "\n";
  562         }
  563     }
  564     
  565     return out;
  566 }
  567 
  568 void RbxGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
  569 {
  570     ret << "begin\n" << vCS() << " = " << gotoDest << " ";
  571     rbxGoto(ret, "_again") << 
  572         "\nend\n";
  573 }
  574 
  575 void RbxGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  576 {
  577     ret << "begin\n" << vCS() << " = (";
  578     INLINE_LIST( ret, ilItem->children, 0, inFinish );
  579     ret << ")";
  580     rbxGoto(ret, "_again") << 
  581         "\nend\n";
  582 }
  583 
  584 void RbxGotoCodeGen::CURS( ostream &ret, bool inFinish )
  585 {
  586     ret << "(_ps)";
  587 }
  588 
  589 void RbxGotoCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
  590 {
  591     ret << "(" << vCS() << ")";
  592 }
  593 
  594 void RbxGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
  595 {
  596     ret << vCS() << " = " << nextDest << ";";
  597 }
  598 
  599 void RbxGotoCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  600 {
  601     ret << vCS() << " = (";
  602     INLINE_LIST( ret, ilItem->children, 0, inFinish );
  603     ret << ");";
  604 }
  605 
  606 void RbxGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
  607 {
  608     if ( prePushExpr != 0 ) {
  609         ret << "{";
  610         INLINE_LIST( ret, prePushExpr, 0, false );
  611     }
  612 
  613     ret << "begin\n" 
  614         << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << 
  615         callDest << "; ";
  616     rbxGoto(ret, "_again") << 
  617         "\nend\n";
  618 
  619     if ( prePushExpr != 0 )
  620         ret << "}";
  621 }
  622 
  623 void RbxGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
  624 {
  625     if ( prePushExpr != 0 ) {
  626         ret << "{";
  627         INLINE_LIST( ret, prePushExpr, 0, false );
  628     }
  629 
  630     ret << "begin\n" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
  631     INLINE_LIST( ret, ilItem->children, targState, inFinish );
  632     ret << "); ";
  633     rbxGoto(ret, "_again") << 
  634         "\nend\n";
  635 
  636     if ( prePushExpr != 0 )
  637         ret << "}";
  638 }
  639 
  640 void RbxGotoCodeGen::RET( ostream &ret, bool inFinish )
  641 {
  642     ret << "begin\n" << vCS() << " = " << STACK() << "[--" << TOP() << "]; " ;
  643 
  644     if ( postPopExpr != 0 ) {
  645         ret << "{";
  646         INLINE_LIST( ret, postPopExpr, 0, false );
  647         ret << "}";
  648     }
  649 
  650     rbxGoto(ret, "_again") << 
  651         "\nend\n";
  652 }
  653 
  654 void RbxGotoCodeGen::BREAK( ostream &ret, int targState )
  655 {
  656     outLabelUsed = true;
  657 
  658     out <<
  659         "   begin\n"
  660         "       " << P() << " += 1\n"
  661         "       "; rbxGoto(ret, "_out") << "\n" 
  662         "   end\n";
  663 }
  664 
  665 void RbxGotoCodeGen::writeData()
  666 {
  667     if ( redFsm->anyActions() ) {
  668         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
  669         ACTIONS_ARRAY();
  670         CLOSE_ARRAY() <<
  671             "\n";
  672     }
  673 
  674     if ( redFsm->anyToStateActions() ) {
  675         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  676         TO_STATE_ACTIONS();
  677         CLOSE_ARRAY() <<
  678             "\n";
  679     }
  680 
  681     if ( redFsm->anyFromStateActions() ) {
  682         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  683         FROM_STATE_ACTIONS();
  684         CLOSE_ARRAY() <<
  685             "\n";
  686     }
  687 
  688     if ( redFsm->anyEofActions() ) {
  689         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
  690         EOF_ACTIONS();
  691         CLOSE_ARRAY() <<
  692             "\n";
  693     }
  694 
  695     STATE_IDS();
  696 }
  697 
  698 void RbxGotoCodeGen::writeExec()
  699 {
  700     outLabelUsed = false;
  701 
  702     out << "    begin\n";
  703 
  704     out << "    Rubinius.asm { @labels = Hash.new { |h,k| h[k] = new_label } }\n";
  705 
  706     if ( redFsm->anyRegCurStateRef() )
  707         out << "    _ps = 0;\n";
  708 
  709     if ( redFsm->anyToStateActions() || redFsm->anyRegActions() 
  710          || redFsm->anyFromStateActions() )
  711     {
  712                 out <<  " _acts, _nacts = nil\n";
  713     }
  714 
  715     if ( redFsm->anyConditions() )
  716         out << "        _widec = nil\n";
  717 
  718     out << "\n";
  719 
  720     if ( !noEnd ) {
  721         outLabelUsed = true;
  722         out << 
  723             "   if ( " << P() << " == " << PE() << " )\n";
  724         rbxGoto(out << "        ", "_out") << "\n" <<
  725             "   end\n";
  726     }
  727 
  728     if ( redFsm->errState != 0 ) {
  729         outLabelUsed = true;
  730         out << 
  731             "   if ( " << vCS() << " == " << redFsm->errState->id << " )\n";
  732         rbxGoto(out << "        ", "_out") << "\n" <<
  733             "   end\n";
  734     }
  735 
  736     rbxLabel(out, "_resume") << "\n";
  737 
  738     if ( redFsm->anyFromStateActions() ) {
  739         out <<
  740 
  741             "   _acts = " << ARR_OFF( A(), FSA() + "[" + vCS() + "]" ) << ";\n"
  742             "   _nacts = " << " *_acts++;\n"
  743             "   while ( _nacts-- > 0 ) {\n"
  744             "       switch ( *_acts++ ) {\n";
  745         FROM_STATE_ACTION_SWITCH();
  746         out <<
  747             "       }\n"
  748             "   }\n"
  749             "\n";
  750     }
  751 
  752     out <<
  753         "   case ( " << vCS() << " )\n";
  754     STATE_GOTOS();
  755     out <<
  756         "   end # case\n"
  757         "\n";
  758     TRANSITIONS() <<
  759         "\n";
  760 
  761     if ( redFsm->anyRegActions() )
  762         EXEC_FUNCS() << "\n";
  763 
  764 
  765     rbxLabel(out, "_again") << "\n";
  766 
  767     if ( redFsm->anyToStateActions() ) {
  768         out <<
  769             "   _acts = " << ARR_OFF( A(), TSA() + "[" + vCS() + "]" ) << ";\n"
  770             "   _nacts = " << " *_acts++;\n"
  771             "   while ( _nacts-- > 0 ) {\n"
  772             "       switch ( *_acts++ ) {\n";
  773         TO_STATE_ACTION_SWITCH();
  774         out <<
  775             "       }\n"
  776             "   }\n"
  777             "\n";
  778     }
  779 
  780     if ( redFsm->errState != 0 ) {
  781         outLabelUsed = true;
  782         out << 
  783             "   if ( " << vCS() << " == " << redFsm->errState->id << " )\n";
  784         rbxGoto(out << "        ", "_out") << "\n" <<
  785             "   end" << "\n";
  786     }
  787 
  788     if ( !noEnd ) {
  789         out <<  "   "  << P() << " += 1\n"
  790             "   if ( " << P() << " != " << PE() << " )\n";
  791         rbxGoto(out << "        ", "_resume") << "\n" <<
  792             "   end" << "\n";
  793     }
  794     else {
  795         out << 
  796             "   " << P() << " += 1;\n";
  797         rbxGoto(out << "    ", "_resume") << "\n";
  798     }
  799 
  800     if ( outLabelUsed )
  801         rbxLabel(out, "_out") << "\n";
  802 
  803     out << "    end\n";
  804 }
  805 
  806 void RbxGotoCodeGen::writeEOF()
  807 {
  808     if ( redFsm->anyEofActions() ) {
  809         out << 
  810             "   {\n"
  811             "    _acts = " << 
  812             ARR_OFF( A(), EA() + "[" + vCS() + "]" ) << ";\n"
  813             "   " << " _nacts = " << " *_acts++;\n"
  814             "   while ( _nacts-- > 0 ) {\n"
  815             "       switch ( *_acts++ ) {\n";
  816         EOF_ACTION_SWITCH();
  817         out <<
  818             "       }\n"
  819             "   }\n"
  820             "   }\n"
  821             "\n";
  822     }
  823 }
  824 
  825 /*
  826  * Local Variables:
  827  * mode: c++
  828  * indent-tabs-mode: 1
  829  * c-file-style: "bsd"
  830  * End:
  831  */