std::ostream &GraphvizDotGen::TRANS_ACTION( RedStateAp *fromState, RedTransAp *trans ) { int n = 0; RedAction *actions[3]; if ( fromState->fromStateAction != 0 ) actions[n++] = fromState->fromStateAction; if ( trans->action != 0 ) actions[n++] = trans->action; if ( trans->targ != 0 && trans->targ->toStateAction != 0 ) actions[n++] = trans->targ->toStateAction; if ( n > 0 ) out << " / "; /* Loop the existing actions and write out what's there. */ for ( int a = 0; a < n; a++ ) { for ( GenActionTable::Iter actIt = actions[a]->key.first(); actIt.lte(); actIt++ ) { GenAction *action = actIt->value; out << action->nameOrLoc(); if ( a < n-1 || !actIt.last() ) out << ", "; } } return out; }
/* Gather various info on the machine. */ void CodeGenData::analyzeMachine() { /* Find the true count of action references. */ findFinalActionRefs(); /* Check if there are any calls in action code. */ for ( GenActionList::Iter act = actionList; act.lte(); act++ ) { /* Record the occurrence of various kinds of actions. */ if ( act->numToStateRefs > 0 ) redFsm->bAnyToStateActions = true; if ( act->numFromStateRefs > 0 ) redFsm->bAnyFromStateActions = true; if ( act->numEofRefs > 0 ) redFsm->bAnyEofActions = true; if ( act->numTransRefs > 0 ) redFsm->bAnyRegActions = true; /* Recurse through the action's parse tree looking for various things. */ analyzeAction( act, act->inlineList ); } /* Analyze reduced action lists. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { for ( GenActionTable::Iter act = redAct->key; act.lte(); act++ ) analyzeActionList( redAct, act->value->inlineList ); } /* Find states that have transitions with actions that have next * statements. */ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Check any actions out of outSinge. */ for ( RedTransList::Iter rtel = st->outSingle; rtel.lte(); rtel++ ) { if ( rtel->value->action != 0 && rtel->value->action->anyCurStateRef() ) st->bAnyRegCurStateRef = true; } /* Check any actions out of outRange. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { if ( rtel->value->action != 0 && rtel->value->action->anyCurStateRef() ) st->bAnyRegCurStateRef = true; } /* Check any action out of default. */ if ( st->defTrans != 0 && st->defTrans->action != 0 && st->defTrans->action->anyCurStateRef() ) st->bAnyRegCurStateRef = true; if ( st->stateCondList.length() > 0 ) redFsm->bAnyConditions = true; if ( st->eofTrans != 0 ) redFsm->bAnyEofTrans = true; } /* Assign ids to actions that are referenced. */ assignActionIds(); /* Set the maximums of various values used for deciding types. */ setValueLimits(); }
/* Write out the array of actions. */ std::ostream &JavaTabCodeGen::ACTIONS_ARRAY() { ARRAY_ITEM( INT(0), false ); for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { /* Write out the length, which will never be the last character. */ ARRAY_ITEM( INT(act->key.length()), false ); for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) ARRAY_ITEM( INT(item->value->actionId), (act.last() && item.last()) ); } return out; }
std::ostream &GraphvizDotGen::ACTION( RedAction *action ) { /* The action. */ out << " / "; for ( GenActionTable::Iter actIt = action->key.first(); actIt.lte(); actIt++ ) { GenAction *action = actIt->value; if ( action->name != 0 ) out << action->name; else out << action->loc.line << ":" << action->loc.col; if ( !actIt.last() ) out << ", "; } return out; }
/* Called from before writing the gotos for each state. */ void SplitCodeGen::GOTO_HEADER( RedStateAp *state, bool stateInPartition ) { bool anyWritten = IN_TRANS_ACTIONS( state ); if ( state->labelNeeded ) out << L"st" << state->id << L":\n"; if ( state->toStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->toStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, state->id, false, state->toStateAction->anyNextStmt() ); } } /* Advance and test buffer pos. */ if ( state->labelNeeded ) { if ( !noEnd ) { out << L" if ( ++" << P() << L" == " << PE() << L" )\n" L" goto _out" << state->id << L";\n"; } else { out << L" " << P() << L" += 1;\n"; } } /* Give the state a switch case. */ out << L"case " << state->id << L":\n"; if ( state->fromStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ anyWritten = true; for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, state->id, false, state->fromStateAction->anyNextStmt() ); } } if ( anyWritten ) genLineDirective( out ); /* Record the prev state if necessary. */ if ( state->anyRegCurStateRef() ) out << L" _ps = " << state->id << L";\n"; }
/* Write out the array of actions. */ std::ostream &JSCodeGen::ACTIONS_ARRAY() { START_ARRAY_LINE(); int totalActions = 0; ARRAY_ITEM( INT(0), ++totalActions, false ); for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { /* Write out the length, which will never be the last character. */ ARRAY_ITEM( INT(act->key.length()), ++totalActions, false ); for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) { ARRAY_ITEM( INT(item->value->actionId), ++totalActions, (act.last() && item.last()) ); } } END_ARRAY_LINE(); return out; }
std::wostream &SplitCodeGen::PART_TRANS( int partition ) { for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { if ( trans->partitionBoundary ) { out << L"ptr" << trans->id << L":\n"; if ( trans->action != 0 ) { /* If the action contains a next, then we must preload the current * state since the action may or may not set it. */ if ( trans->action->anyNextStmt() ) out << L" " << vCS() << L" = " << trans->targ->id << L";\n"; /* Write each action in the list. */ for ( GenActionTable::Iter item = trans->action->key; item.lte(); item++ ) { ACTION( out, item->value, trans->targ->id, false, trans->action->anyNextStmt() ); } } out << L" goto pst" << trans->targ->id << L";\n"; trans->targ->partitionBoundary = true; } } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { if ( st->partitionBoundary ) { out << L" pst" << st->id << L":\n" L" " << vCS() << L" = " << st->id << L";\n"; if ( st->toStateAction != 0 ) { /* Remember that we wrote an action. Write every action in the list. */ for ( GenActionTable::Iter item = st->toStateAction->key; item.lte(); item++ ) { ACTION( out, item->value, st->id, false, st->toStateAction->anyNextStmt() ); } genLineDirective( out ); } ptOutLabelUsed = true; out << L" goto _pt_out; \n"; } } return out; }
std::ostream &GoFGotoCodeGen::EOF_ACTION_SWITCH( int level ) { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << TABS(level) << "case " << redAct->actListId+1 << ":" << endl; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true, false ); } } genLineDirective( out ); return out; }
std::wostream &FGotoCodeGen::EXEC_ACTIONS() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* We are at the start of a glob, write the case. */ out << L"f" << redAct->actListId << L":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << L"\tgoto _again;\n"; } } return out; }
/* Write out the function switch. This switch is keyed on the values * of the func index. */ std::ostream &RubyFTabCodeGen::ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* Write the entry label. */ out << "\twhen " << redAct->actListId+1 << " then\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); } } genLineDirective( out ); return out; }
/* Write out the function switch. This switch is keyed on the values * of the func index. */ std::wostream &FGotoCodeGen::FROM_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numFromStateRefs > 0 ) { /* Write the entry label. */ out << L"\tcase " << redAct->actListId+1 << L":\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false, false ); out << L"\tbreak;\n"; } } genLineDirective( out ); return out; }
/* Write out the function switch. This switch is keyed on the values * of the func index. */ std::wostream &OCamlFFlatCodeGen::TO_STATE_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numToStateRefs > 0 ) { /* Write the entry label. */ out << L"\t| " << redAct->actListId+1 << L" ->\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << L"\t()\n"; } } genLineDirective( out ); return out; }
std::ostream &OCamlFGotoCodeGen::EOF_ACTION_SWITCH() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numEofRefs > 0 ) { /* Write the entry label. */ out << "\t| " << redAct->actListId+1 << " ->\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, true ); // out << "\tbreak;\n"; } } genLineDirective( out ); return out; }
std::ostream &OCamlFGotoCodeGen::EXEC_ACTIONS() { /* Loop the actions. */ for ( GenActionTableMap::Iter redAct = redFsm->actionMap; redAct.lte(); redAct++ ) { if ( redAct->numTransRefs > 0 ) { /* We are at the start of a glob, write the case. */ out << "and f" << redAct->actListId << " () =\n"; out << "\tbegin try\n"; /* Write each action in the list of action items. */ for ( GenActionTable::Iter item = redAct->key; item.lte(); item++ ) ACTION( out, item->value, 0, false ); out << "\twith Goto_again -> () end;\n"; out << "\tdo_again ()\n"; } } return out; }
/* Write out the array of actions. */ std::ostream &GoCodeGen::ACTIONS_ARRAY() { out << " 0, "; int totalActions = 1; for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { /* Write out the length, which will never be the last character. */ out << act->key.length() << ", "; if ( totalActions++ % IALL == 0 ) out << endl << " "; for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) { out << item->value->actionId << ", "; if ( ! (act.last() && item.last()) ) { if ( totalActions++ % IALL == 0 ) out << endl << " "; } } } out << endl; return out; }
void SplitCodeGen::setLabelsNeeded( RedStateAp *fromState, RedTransAp *trans ) { /* In the split code gen we don't need labels for transitions across * partitions. */ if ( fromState->partition == trans->targ->partition ) { /* If there is no action with a next statement, then the label will be * needed. */ trans->labelNeeded = true; if ( trans->action == 0 || !trans->action->anyNextStmt() ) trans->targ->labelNeeded = true; } /* Need labels for states that have goto or calls in action code * invoked on characters (ie, not from out action code). */ if ( trans->action != 0 ) { /* Loop the actions. */ for ( GenActionTable::Iter act = trans->action->key; act.lte(); act++ ) { /* Get the action and walk it's tree. */ setLabelsNeeded( fromState, act->value->inlineList ); } } }
/* Write out the array of actions. */ std::ostream &FsmCodeGen::ACTIONS_ARRAY() { out << "\t0, "; int totalActions = 1; for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) { /* Write out the length, which will never be the last character. */ out << act->key.length() << ", "; /* Put in a line break every 8 */ if ( totalActions++ % 8 == 7 ) out << "\n\t"; for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) { out << item->value->actionId; if ( ! (act.last() && item.last()) ) out << ", "; /* Put in a line break every 8 */ if ( totalActions++ % 8 == 7 ) out << "\n\t"; } } out << "\n"; return out; }
void CodeGenData::setValueLimits() { redFsm->maxSingleLen = 0; redFsm->maxRangeLen = 0; redFsm->maxKeyOffset = 0; redFsm->maxIndexOffset = 0; redFsm->maxActListId = 0; redFsm->maxActionLoc = 0; redFsm->maxActArrItem = 0; redFsm->maxSpan = 0; redFsm->maxCondSpan = 0; redFsm->maxFlatIndexOffset = 0; redFsm->maxCondOffset = 0; redFsm->maxCondLen = 0; redFsm->maxCondSpaceId = 0; redFsm->maxCondIndexOffset = 0; /* In both of these cases the 0 index is reserved for no value, so the max * is one more than it would be if they started at 0. */ redFsm->maxIndex = redFsm->transSet.length(); redFsm->maxCond = condSpaceList.length(); /* The nextStateId - 1 is the last state id assigned. */ redFsm->maxState = redFsm->nextStateId - 1; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { if ( csi->condSpaceId > redFsm->maxCondSpaceId ) redFsm->maxCondSpaceId = csi->condSpaceId; } for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Maximum cond length. */ if ( st->stateCondList.length() > redFsm->maxCondLen ) redFsm->maxCondLen = st->stateCondList.length(); /* Maximum single length. */ if ( st->outSingle.length() > redFsm->maxSingleLen ) redFsm->maxSingleLen = st->outSingle.length(); /* Maximum range length. */ if ( st->outRange.length() > redFsm->maxRangeLen ) redFsm->maxRangeLen = st->outRange.length(); /* The key offset index offset for the state after last is not used, skip it.. */ if ( ! st.last() ) { redFsm->maxCondOffset += st->stateCondList.length(); redFsm->maxKeyOffset += st->outSingle.length() + st->outRange.length()*2; redFsm->maxIndexOffset += st->outSingle.length() + st->outRange.length() + 2; } /* Max cond span. */ if ( st->condList != 0 ) { unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey ); if ( span > redFsm->maxCondSpan ) redFsm->maxCondSpan = span; } /* Max key span. */ if ( st->transList != 0 ) { unsigned long long span = keyOps->span( st->lowKey, st->highKey ); if ( span > redFsm->maxSpan ) redFsm->maxSpan = span; } /* Max cond index offset. */ if ( ! st.last() ) { if ( st->condList != 0 ) redFsm->maxCondIndexOffset += keyOps->span( st->condLowKey, st->condHighKey ); } /* Max flat index offset. */ if ( ! st.last() ) { if ( st->transList != 0 ) redFsm->maxFlatIndexOffset += keyOps->span( st->lowKey, st->highKey ); redFsm->maxFlatIndexOffset += 1; } } for ( GenActionTableMap::Iter at = redFsm->actionMap; at.lte(); at++ ) { /* Maximum id of action lists. */ if ( at->actListId+1 > redFsm->maxActListId ) redFsm->maxActListId = at->actListId+1; /* Maximum location of items in action array. */ if ( at->location+1 > redFsm->maxActionLoc ) redFsm->maxActionLoc = at->location+1; /* Maximum values going into the action array. */ if ( at->key.length() > redFsm->maxActArrItem ) redFsm->maxActArrItem = at->key.length(); for ( GenActionTable::Iter item = at->key; item.lte(); item++ ) { if ( item->value->actionId > redFsm->maxActArrItem ) redFsm->maxActArrItem = item->value->actionId; } } }
void CodeGenData::findFinalActionRefs() { for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { /* Rerence count out of single transitions. */ for ( RedTransList::Iter rtel = st->outSingle; rtel.lte(); rtel++ ) { if ( rtel->value->action != 0 ) { rtel->value->action->numTransRefs += 1; for ( GenActionTable::Iter item = rtel->value->action->key; item.lte(); item++ ) item->value->numTransRefs += 1; } } /* Reference count out of range transitions. */ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) { if ( rtel->value->action != 0 ) { rtel->value->action->numTransRefs += 1; for ( GenActionTable::Iter item = rtel->value->action->key; item.lte(); item++ ) item->value->numTransRefs += 1; } } /* Reference count default transition. */ if ( st->defTrans != 0 && st->defTrans->action != 0 ) { st->defTrans->action->numTransRefs += 1; for ( GenActionTable::Iter item = st->defTrans->action->key; item.lte(); item++ ) item->value->numTransRefs += 1; } /* Reference count eof transitions. */ if ( st->eofTrans != 0 && st->eofTrans->action != 0 ) { st->eofTrans->action->numTransRefs += 1; for ( GenActionTable::Iter item = st->eofTrans->action->key; item.lte(); item++ ) item->value->numTransRefs += 1; } /* Reference count to state actions. */ if ( st->toStateAction != 0 ) { st->toStateAction->numToStateRefs += 1; for ( GenActionTable::Iter item = st->toStateAction->key; item.lte(); item++ ) item->value->numToStateRefs += 1; } /* Reference count from state actions. */ if ( st->fromStateAction != 0 ) { st->fromStateAction->numFromStateRefs += 1; for ( GenActionTable::Iter item = st->fromStateAction->key; item.lte(); item++ ) item->value->numFromStateRefs += 1; } /* Reference count EOF actions. */ if ( st->eofAction != 0 ) { st->eofAction->numEofRefs += 1; for ( GenActionTable::Iter item = st->eofAction->key; item.lte(); item++ ) item->value->numEofRefs += 1; } } }