rbxgoto.cpp 22 KB

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