mlflat.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. /*
  2. * Copyright 2004-2006 Adrian Thurston <thurston@complang.org>
  3. * 2004 Erich Ocean <eric.ocean@ampede.com>
  4. * 2005 Alan West <alan@alanz.com>
  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. #include <sstream>
  23. #include "ragel.h"
  24. #include "mlflat.h"
  25. #include "redfsm.h"
  26. #include "gendata.h"
  27. std::ostream &OCamlFlatCodeGen::TO_STATE_ACTION( RedStateAp *state )
  28. {
  29. int act = 0;
  30. if ( state->toStateAction != 0 )
  31. act = state->toStateAction->location+1;
  32. out << act;
  33. return out;
  34. }
  35. std::ostream &OCamlFlatCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  36. {
  37. int act = 0;
  38. if ( state->fromStateAction != 0 )
  39. act = state->fromStateAction->location+1;
  40. out << act;
  41. return out;
  42. }
  43. std::ostream &OCamlFlatCodeGen::EOF_ACTION( RedStateAp *state )
  44. {
  45. int act = 0;
  46. if ( state->eofAction != 0 )
  47. act = state->eofAction->location+1;
  48. out << act;
  49. return out;
  50. }
  51. std::ostream &OCamlFlatCodeGen::TRANS_ACTION( RedTransAp *trans )
  52. {
  53. /* If there are actions, emit them. Otherwise emit zero. */
  54. int act = 0;
  55. if ( trans->action != 0 )
  56. act = trans->action->location+1;
  57. out << act;
  58. return out;
  59. }
  60. std::ostream &OCamlFlatCodeGen::TO_STATE_ACTION_SWITCH()
  61. {
  62. /* Walk the list of functions, printing the cases. */
  63. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  64. /* Write out referenced actions. */
  65. if ( act->numToStateRefs > 0 ) {
  66. /* Write the case label, the action and the case break */
  67. out << "\t| " << act->actionId << " ->\n";
  68. ACTION( out, act, 0, false );
  69. out << "\t()\n";
  70. }
  71. }
  72. genLineDirective( out );
  73. return out;
  74. }
  75. std::ostream &OCamlFlatCodeGen::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 << "\t| " << act->actionId << " ->\n";
  83. ACTION( out, act, 0, false );
  84. out << "\t()\n";
  85. }
  86. }
  87. genLineDirective( out );
  88. return out;
  89. }
  90. std::ostream &OCamlFlatCodeGen::EOF_ACTION_SWITCH()
  91. {
  92. /* Walk the list of functions, printing the cases. */
  93. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  94. /* Write out referenced actions. */
  95. if ( act->numEofRefs > 0 ) {
  96. /* Write the case label, the action and the case break */
  97. out << "\t| " << act->actionId << " ->\n";
  98. ACTION( out, act, 0, true );
  99. out << "\t()\n";
  100. }
  101. }
  102. genLineDirective( out );
  103. return out;
  104. }
  105. std::ostream &OCamlFlatCodeGen::ACTION_SWITCH()
  106. {
  107. /* Walk the list of functions, printing the cases. */
  108. for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  109. /* Write out referenced actions. */
  110. if ( act->numTransRefs > 0 ) {
  111. /* Write the case label, the action and the case break */
  112. out << "\t| " << act->actionId << " ->\n";
  113. ACTION( out, act, 0, false );
  114. out << "\t()\n";
  115. }
  116. }
  117. genLineDirective( out );
  118. return out;
  119. }
  120. std::ostream &OCamlFlatCodeGen::FLAT_INDEX_OFFSET()
  121. {
  122. out << "\t";
  123. int totalStateNum = 0, curIndOffset = 0;
  124. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  125. /* Write the index offset. */
  126. out << curIndOffset;
  127. if ( !st.last() ) {
  128. out << ARR_SEP();
  129. if ( ++totalStateNum % IALL == 0 )
  130. out << "\n\t";
  131. }
  132. /* Move the index offset ahead. */
  133. if ( st->transList != 0 )
  134. curIndOffset += keyOps->span( st->lowKey, st->highKey );
  135. if ( st->defTrans != 0 )
  136. curIndOffset += 1;
  137. }
  138. out << "\n";
  139. return out;
  140. }
  141. std::ostream &OCamlFlatCodeGen::KEY_SPANS()
  142. {
  143. out << "\t";
  144. int totalStateNum = 0;
  145. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  146. /* Write singles length. */
  147. unsigned long long span = 0;
  148. if ( st->transList != 0 )
  149. span = keyOps->span( st->lowKey, st->highKey );
  150. out << span;
  151. if ( !st.last() ) {
  152. out << ARR_SEP();
  153. if ( ++totalStateNum % IALL == 0 )
  154. out << "\n\t";
  155. }
  156. }
  157. out << "\n";
  158. return out;
  159. }
  160. std::ostream &OCamlFlatCodeGen::TO_STATE_ACTIONS()
  161. {
  162. out << "\t";
  163. int totalStateNum = 0;
  164. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  165. /* Write any eof action. */
  166. TO_STATE_ACTION(st);
  167. if ( !st.last() ) {
  168. out << ARR_SEP();
  169. if ( ++totalStateNum % IALL == 0 )
  170. out << "\n\t";
  171. }
  172. }
  173. out << "\n";
  174. return out;
  175. }
  176. std::ostream &OCamlFlatCodeGen::FROM_STATE_ACTIONS()
  177. {
  178. out << "\t";
  179. int totalStateNum = 0;
  180. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  181. /* Write any eof action. */
  182. FROM_STATE_ACTION(st);
  183. if ( !st.last() ) {
  184. out << ARR_SEP();
  185. if ( ++totalStateNum % IALL == 0 )
  186. out << "\n\t";
  187. }
  188. }
  189. out << "\n";
  190. return out;
  191. }
  192. std::ostream &OCamlFlatCodeGen::EOF_ACTIONS()
  193. {
  194. out << "\t";
  195. int totalStateNum = 0;
  196. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  197. /* Write any eof action. */
  198. EOF_ACTION(st);
  199. if ( !st.last() ) {
  200. out << ARR_SEP();
  201. if ( ++totalStateNum % IALL == 0 )
  202. out << "\n\t";
  203. }
  204. }
  205. out << "\n";
  206. return out;
  207. }
  208. std::ostream &OCamlFlatCodeGen::EOF_TRANS()
  209. {
  210. out << "\t";
  211. int totalStateNum = 0;
  212. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  213. /* Write any eof action. */
  214. long trans = 0;
  215. if ( st->eofTrans != 0 ) {
  216. assert( st->eofTrans->pos >= 0 );
  217. trans = st->eofTrans->pos+1;
  218. }
  219. out << trans;
  220. if ( !st.last() ) {
  221. out << ARR_SEP();
  222. if ( ++totalStateNum % IALL == 0 )
  223. out << "\n\t";
  224. }
  225. }
  226. out << "\n";
  227. return out;
  228. }
  229. std::ostream &OCamlFlatCodeGen::COND_KEYS()
  230. {
  231. out << '\t';
  232. int totalTrans = 0;
  233. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  234. /* Emit just cond low key and cond high key. */
  235. out << ALPHA_KEY( st->condLowKey ) << ARR_SEP();
  236. out << ALPHA_KEY( st->condHighKey ) << ARR_SEP();
  237. if ( ++totalTrans % IALL == 0 )
  238. out << "\n\t";
  239. }
  240. /* Output one last number so we don't have to figure out when the last
  241. * entry is and avoid writing a comma. */
  242. out << /*"(char) " <<*/ 0 << "\n";
  243. return out;
  244. }
  245. std::ostream &OCamlFlatCodeGen::COND_KEY_SPANS()
  246. {
  247. out << "\t";
  248. int totalStateNum = 0;
  249. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  250. /* Write singles length. */
  251. unsigned long long span = 0;
  252. if ( st->condList != 0 )
  253. span = keyOps->span( st->condLowKey, st->condHighKey );
  254. out << span;
  255. if ( !st.last() ) {
  256. out << ARR_SEP();
  257. if ( ++totalStateNum % IALL == 0 )
  258. out << "\n\t";
  259. }
  260. }
  261. out << "\n";
  262. return out;
  263. }
  264. std::ostream &OCamlFlatCodeGen::CONDS()
  265. {
  266. int totalTrans = 0;
  267. out << '\t';
  268. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  269. if ( st->condList != 0 ) {
  270. /* Walk the singles. */
  271. unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey );
  272. for ( unsigned long long pos = 0; pos < span; pos++ ) {
  273. if ( st->condList[pos] != 0 )
  274. out << st->condList[pos]->condSpaceId + 1 << ARR_SEP();
  275. else
  276. out << "0" << ARR_SEP();
  277. if ( ++totalTrans % IALL == 0 )
  278. out << "\n\t";
  279. }
  280. }
  281. }
  282. /* Output one last number so we don't have to figure out when the last
  283. * entry is and avoid writing a comma. */
  284. out << 0 << "\n";
  285. return out;
  286. }
  287. std::ostream &OCamlFlatCodeGen::COND_INDEX_OFFSET()
  288. {
  289. out << "\t";
  290. int totalStateNum = 0, curIndOffset = 0;
  291. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  292. /* Write the index offset. */
  293. out << curIndOffset;
  294. if ( !st.last() ) {
  295. out << ARR_SEP();
  296. if ( ++totalStateNum % IALL == 0 )
  297. out << "\n\t";
  298. }
  299. /* Move the index offset ahead. */
  300. if ( st->condList != 0 )
  301. curIndOffset += keyOps->span( st->condLowKey, st->condHighKey );
  302. }
  303. out << "\n";
  304. return out;
  305. }
  306. std::ostream &OCamlFlatCodeGen::KEYS()
  307. {
  308. out << '\t';
  309. int totalTrans = 0;
  310. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  311. /* Emit just low key and high key. */
  312. out << ALPHA_KEY( st->lowKey ) << ARR_SEP();
  313. out << ALPHA_KEY( st->highKey ) << ARR_SEP();
  314. if ( ++totalTrans % IALL == 0 )
  315. out << "\n\t";
  316. }
  317. /* Output one last number so we don't have to figure out when the last
  318. * entry is and avoid writing a comma. */
  319. out << /*"(char) " <<*/ 0 << "\n";
  320. return out;
  321. }
  322. std::ostream &OCamlFlatCodeGen::INDICIES()
  323. {
  324. int totalTrans = 0;
  325. out << '\t';
  326. for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  327. if ( st->transList != 0 ) {
  328. /* Walk the singles. */
  329. unsigned long long span = keyOps->span( st->lowKey, st->highKey );
  330. for ( unsigned long long pos = 0; pos < span; pos++ ) {
  331. out << st->transList[pos]->id << ARR_SEP();
  332. if ( ++totalTrans % IALL == 0 )
  333. out << "\n\t";
  334. }
  335. }
  336. /* The state's default index goes next. */
  337. if ( st->defTrans != 0 )
  338. out << st->defTrans->id << ARR_SEP();
  339. if ( ++totalTrans % IALL == 0 )
  340. out << "\n\t";
  341. }
  342. /* Output one last number so we don't have to figure out when the last
  343. * entry is and avoid writing a comma. */
  344. out << 0 << "\n";
  345. return out;
  346. }
  347. std::ostream &OCamlFlatCodeGen::TRANS_TARGS()
  348. {
  349. /* Transitions must be written ordered by their id. */
  350. RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
  351. for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
  352. transPtrs[trans->id] = trans;
  353. /* Keep a count of the num of items in the array written. */
  354. out << '\t';
  355. int totalStates = 0;
  356. for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
  357. /* Record the position, need this for eofTrans. */
  358. RedTransAp *trans = transPtrs[t];
  359. trans->pos = t;
  360. /* Write out the target state. */
  361. out << trans->targ->id;
  362. if ( t < redFsm->transSet.length()-1 ) {
  363. out << ARR_SEP();
  364. if ( ++totalStates % IALL == 0 )
  365. out << "\n\t";
  366. }
  367. }
  368. out << "\n";
  369. delete[] transPtrs;
  370. return out;
  371. }
  372. std::ostream &OCamlFlatCodeGen::TRANS_ACTIONS()
  373. {
  374. /* Transitions must be written ordered by their id. */
  375. RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
  376. for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
  377. transPtrs[trans->id] = trans;
  378. /* Keep a count of the num of items in the array written. */
  379. out << '\t';
  380. int totalAct = 0;
  381. for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
  382. /* Write the function for the transition. */
  383. RedTransAp *trans = transPtrs[t];
  384. TRANS_ACTION( trans );
  385. if ( t < redFsm->transSet.length()-1 ) {
  386. out << ARR_SEP();
  387. if ( ++totalAct % IALL == 0 )
  388. out << "\n\t";
  389. }
  390. }
  391. out << "\n";
  392. delete[] transPtrs;
  393. return out;
  394. }
  395. void OCamlFlatCodeGen::LOCATE_TRANS()
  396. {
  397. std::ostringstream temp;
  398. temp << "inds + (\n"
  399. " if slen > 0 && " << AT( K(), "keys" ) << " <= " << GET_WIDE_KEY() << " &&\n"
  400. " " << GET_WIDE_KEY() << " <= " << AT( K(), "keys+1" ) << " then\n"
  401. " " << GET_WIDE_KEY() << " - " << AT(K(), "keys" ) << " else slen)";
  402. out <<
  403. " let keys = " << vCS() << " lsl 1 in\n"
  404. " let inds = " << AT( IO(), vCS() ) << " in\n"
  405. "\n"
  406. " let slen = " << AT( SP(), vCS() ) << " in\n"
  407. " state.trans <- " << AT( I(), temp.str() ) << ";\n"
  408. "\n";
  409. }
  410. void OCamlFlatCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
  411. {
  412. ret << "begin " << vCS() << " <- " << gotoDest << "; " <<
  413. CTRL_FLOW() << "raise Goto_again end";
  414. }
  415. void OCamlFlatCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  416. {
  417. ret << "begin " << vCS() << " <- (";
  418. INLINE_LIST( ret, ilItem->children, 0, inFinish );
  419. ret << "); " << CTRL_FLOW() << " raise Goto_again end";
  420. }
  421. void OCamlFlatCodeGen::CURS( ostream &ret, bool inFinish )
  422. {
  423. ret << "(_ps)";
  424. }
  425. void OCamlFlatCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
  426. {
  427. ret << "(" << vCS() << ")";
  428. }
  429. void OCamlFlatCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
  430. {
  431. ret << vCS() << " <- " << nextDest << ";";
  432. }
  433. void OCamlFlatCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  434. {
  435. ret << vCS() << " <- (";
  436. INLINE_LIST( ret, ilItem->children, 0, inFinish );
  437. ret << ");";
  438. }
  439. void OCamlFlatCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
  440. {
  441. if ( prePushExpr != 0 ) {
  442. ret << "begin ";
  443. INLINE_LIST( ret, prePushExpr, 0, false );
  444. }
  445. ret << "begin " << AT( STACK(), POST_INCR(TOP()) ) << " <- " << vCS() << "; ";
  446. ret << vCS() << " <- " << callDest << "; " << CTRL_FLOW() << "raise Goto_again end ";
  447. if ( prePushExpr != 0 )
  448. ret << "end";
  449. }
  450. void OCamlFlatCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
  451. {
  452. if ( prePushExpr != 0 ) {
  453. ret << "begin ";
  454. INLINE_LIST( ret, prePushExpr, 0, false );
  455. }
  456. ret << "begin " << AT(STACK(), POST_INCR(TOP()) ) << " <- " << vCS() << "; " << vCS() << " <- (";
  457. INLINE_LIST( ret, ilItem->children, targState, inFinish );
  458. ret << "); " << CTRL_FLOW() << "raise Goto_again end ";
  459. if ( prePushExpr != 0 )
  460. ret << "end";
  461. }
  462. void OCamlFlatCodeGen::RET( ostream &ret, bool inFinish )
  463. {
  464. ret << "begin " << vCS() << " <- " << AT(STACK(), PRE_DECR(TOP()) ) << "; ";
  465. if ( postPopExpr != 0 ) {
  466. ret << "begin ";
  467. INLINE_LIST( ret, postPopExpr, 0, false );
  468. ret << "end ";
  469. }
  470. ret << CTRL_FLOW() << "raise Goto_again end";
  471. }
  472. void OCamlFlatCodeGen::BREAK( ostream &ret, int targState )
  473. {
  474. outLabelUsed = true;
  475. ret << "begin " << P() << " <- " << P() << " + 1; " << CTRL_FLOW() << "raise Goto_out end";
  476. }
  477. void OCamlFlatCodeGen::writeData()
  478. {
  479. /* If there are any transtion functions then output the array. If there
  480. * are none, don't bother emitting an empty array that won't be used. */
  481. if ( redFsm->anyActions() ) {
  482. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
  483. ACTIONS_ARRAY();
  484. CLOSE_ARRAY() <<
  485. "\n";
  486. }
  487. if ( redFsm->anyConditions() ) {
  488. OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
  489. COND_KEYS();
  490. CLOSE_ARRAY() <<
  491. "\n";
  492. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() );
  493. COND_KEY_SPANS();
  494. CLOSE_ARRAY() <<
  495. "\n";
  496. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() );
  497. CONDS();
  498. CLOSE_ARRAY() <<
  499. "\n";
  500. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() );
  501. COND_INDEX_OFFSET();
  502. CLOSE_ARRAY() <<
  503. "\n";
  504. }
  505. OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
  506. KEYS();
  507. CLOSE_ARRAY() <<
  508. "\n";
  509. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() );
  510. KEY_SPANS();
  511. CLOSE_ARRAY() <<
  512. "\n";
  513. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() );
  514. FLAT_INDEX_OFFSET();
  515. CLOSE_ARRAY() <<
  516. "\n";
  517. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
  518. INDICIES();
  519. CLOSE_ARRAY() <<
  520. "\n";
  521. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  522. TRANS_TARGS();
  523. CLOSE_ARRAY() <<
  524. "\n";
  525. if ( redFsm->anyActions() ) {
  526. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
  527. TRANS_ACTIONS();
  528. CLOSE_ARRAY() <<
  529. "\n";
  530. }
  531. if ( redFsm->anyToStateActions() ) {
  532. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  533. TO_STATE_ACTIONS();
  534. CLOSE_ARRAY() <<
  535. "\n";
  536. }
  537. if ( redFsm->anyFromStateActions() ) {
  538. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  539. FROM_STATE_ACTIONS();
  540. CLOSE_ARRAY() <<
  541. "\n";
  542. }
  543. if ( redFsm->anyEofActions() ) {
  544. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
  545. EOF_ACTIONS();
  546. CLOSE_ARRAY() <<
  547. "\n";
  548. }
  549. if ( redFsm->anyEofTrans() ) {
  550. OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
  551. EOF_TRANS();
  552. CLOSE_ARRAY() <<
  553. "\n";
  554. }
  555. STATE_IDS();
  556. out << "type " << TYPE_STATE() << " = { mutable trans : int; mutable acts : int; mutable nacts : int; }"
  557. << TOP_SEP();
  558. out << "exception Goto_match" << TOP_SEP();
  559. out << "exception Goto_again" << TOP_SEP();
  560. out << "exception Goto_eof_trans" << TOP_SEP();
  561. }
  562. void OCamlFlatCodeGen::COND_TRANSLATE()
  563. {
  564. out <<
  565. " _widec = " << GET_KEY() << ";\n";
  566. out <<
  567. " _keys = " << vCS() << "<<1;\n"
  568. " _conds = " << CO() << "[" << vCS() << "];\n"
  569. // " _keys = " << ARR_OFF( CK(), "(" + vCS() + "<<1)" ) << ";\n"
  570. // " _conds = " << ARR_OFF( C(), CO() + "[" + vCS() + "]" ) << ";\n"
  571. "\n"
  572. " _slen = " << CSP() << "[" << vCS() << "];\n"
  573. " if (_slen > 0 && " << CK() << "[_keys] <="
  574. << GET_WIDE_KEY() << " &&\n"
  575. " " << GET_WIDE_KEY() << " <= " << CK() << "[_keys+1])\n"
  576. " _cond = " << C() << "[_conds+" << GET_WIDE_KEY() << " - " <<
  577. CK() << "[_keys]];\n"
  578. " else\n"
  579. " _cond = 0;"
  580. "\n";
  581. /* XXX This version of the code doesn't work because Mono is weird. Works
  582. * fine in Microsoft's csc, even though the bug report filed claimed it
  583. * didn't.
  584. " _slen = " << CSP() << "[" << vCS() << "];\n"
  585. " _cond = _slen > 0 && " << CK() << "[_keys] <="
  586. << GET_WIDE_KEY() << " &&\n"
  587. " " << GET_WIDE_KEY() << " <= " << CK() << "[_keys+1] ?\n"
  588. " " << C() << "[_conds+" << GET_WIDE_KEY() << " - " << CK()
  589. << "[_keys]] : 0;\n"
  590. "\n";
  591. */
  592. out <<
  593. " switch ( _cond ) {\n";
  594. for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
  595. GenCondSpace *condSpace = csi;
  596. out << " case " << condSpace->condSpaceId + 1 << ": {\n";
  597. out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" <<
  598. KEY(condSpace->baseKey) << " + (" << GET_KEY() <<
  599. " - " << KEY(keyOps->minKey) << "));\n";
  600. for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
  601. out << TABS(2) << "if ( ";
  602. CONDITION( out, *csi );
  603. Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
  604. out << " ) _widec += " << condValOffset << ";\n";
  605. }
  606. out << " }\n";
  607. out << " break;\n";
  608. }
  609. SWITCH_DEFAULT();
  610. out <<
  611. " }\n";
  612. }
  613. void OCamlFlatCodeGen::writeExec()
  614. {
  615. testEofUsed = false;
  616. outLabelUsed = false;
  617. initVarTypes();
  618. out <<
  619. " begin\n";
  620. // " " << slenType << " _slen";
  621. // if ( redFsm->anyRegCurStateRef() )
  622. // out << ", _ps";
  623. // out <<
  624. // " " << transType << " _trans";
  625. // if ( redFsm->anyConditions() )
  626. // out << ", _cond";
  627. // out << ";\n";
  628. // if ( redFsm->anyToStateActions() ||
  629. // redFsm->anyRegActions() || redFsm->anyFromStateActions() )
  630. // {
  631. // out <<
  632. // " int _acts;\n"
  633. // " int _nacts;\n";
  634. // }
  635. // out <<
  636. // " " << "int _keys;\n"
  637. // " " << indsType << " _inds;\n";
  638. /*
  639. " " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n"
  640. " " << PTR_CONST() << ARRAY_TYPE(redFsm->maxIndex) << POINTER() << "_inds;\n";*/
  641. if ( redFsm->anyConditions() ) {
  642. out <<
  643. " " << condsType << " _conds;\n"
  644. " " << WIDE_ALPH_TYPE() << " _widec;\n";
  645. }
  646. out << "\n";
  647. out <<
  648. " let state = { trans = 0; acts = 0; nacts = 0; } in\n"
  649. " let rec do_start () =\n";
  650. if ( !noEnd ) {
  651. testEofUsed = true;
  652. out <<
  653. " if " << P() << " = " << PE() << " then\n"
  654. " do_test_eof ()\n"
  655. "\telse\n";
  656. }
  657. if ( redFsm->errState != 0 ) {
  658. outLabelUsed = true;
  659. out <<
  660. " if " << vCS() << " = " << redFsm->errState->id << " then\n"
  661. " do_out ()\n"
  662. "\telse\n";
  663. }
  664. out << "\tdo_resume ()\n";
  665. out << "and do_resume () =\n";
  666. if ( redFsm->anyFromStateActions() ) {
  667. out <<
  668. " state.acts <- " << AT( FSA(), vCS() ) << ";\n"
  669. " state.nacts <- " << AT( A(), POST_INCR("state.acts") ) << ";\n"
  670. " while " << POST_DECR("state.nacts") << " > 0 do\n"
  671. " begin match " << AT( A(), POST_INCR("state.acts") ) << " with\n";
  672. FROM_STATE_ACTION_SWITCH();
  673. SWITCH_DEFAULT() <<
  674. " end\n"
  675. " done;\n"
  676. "\n";
  677. }
  678. if ( redFsm->anyConditions() )
  679. COND_TRANSLATE();
  680. // out << "\tbegin try\n";
  681. LOCATE_TRANS();
  682. // out << "\twith Goto_match -> () end;\n";
  683. out << "\tdo_eof_trans ()\n";
  684. // if ( redFsm->anyEofTrans() )
  685. out << "and do_eof_trans () =\n";
  686. if ( redFsm->anyRegCurStateRef() )
  687. out << " let ps = " << vCS() << " in\n";
  688. out <<
  689. " " << vCS() << " <- " << AT( TT() ,"state.trans" ) << ";\n"
  690. "\n";
  691. if ( redFsm->anyRegActions() ) {
  692. out <<
  693. "\tbegin try\n"
  694. " match " << AT( TA(), "state.trans" ) << " with\n"
  695. "\t| 0 -> raise Goto_again\n"
  696. "\t| _ ->\n"
  697. " state.acts <- " << AT( TA(), "state.trans" ) << ";\n"
  698. " state.nacts <- " << AT( A(), POST_INCR("state.acts") ) << ";\n"
  699. " while " << POST_DECR("state.nacts") << " > 0 do\n"
  700. " begin match " << AT( A(), POST_INCR("state.acts") ) << " with\n";
  701. ACTION_SWITCH();
  702. SWITCH_DEFAULT() <<
  703. " end;\n"
  704. " done\n"
  705. "\twith Goto_again -> () end;\n";
  706. }
  707. out << "\tdo_again ()\n";
  708. // if ( redFsm->anyRegActions() || redFsm->anyActionGotos() ||
  709. // redFsm->anyActionCalls() || redFsm->anyActionRets() )
  710. out << "\tand do_again () =\n";
  711. if ( redFsm->anyToStateActions() ) {
  712. out <<
  713. " state.acts <- " << AT( TSA(), vCS() ) << ";\n"
  714. " state.nacts <- " << AT( A(), POST_INCR("state.acts") ) << ";\n"
  715. " while " << POST_DECR("state.nacts") << " > 0 do\n"
  716. " begin match " << AT( A(), POST_INCR("state.acts") ) << " with\n";
  717. TO_STATE_ACTION_SWITCH();
  718. SWITCH_DEFAULT() <<
  719. " end\n"
  720. " done;\n"
  721. "\n";
  722. }
  723. if ( redFsm->errState != 0 ) {
  724. outLabelUsed = true;
  725. out <<
  726. " match " << vCS() << " with\n"
  727. "\t| " << redFsm->errState->id << " -> do_out ()\n"
  728. "\t| _ ->\n";
  729. }
  730. out << "\t" << P() << " <- " << P() << " + 1;\n";
  731. if ( !noEnd ) {
  732. out <<
  733. " if " << P() << " <> " << PE() << " then\n"
  734. " do_resume ()\n"
  735. "\telse do_test_eof ()\n";
  736. }
  737. else {
  738. out <<
  739. " do_resume ()\n";
  740. }
  741. // if ( testEofUsed )
  742. out << "and do_test_eof () =\n";
  743. if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
  744. out <<
  745. " if " << P() << " = " << vEOF() << " then\n"
  746. " begin try\n";
  747. if ( redFsm->anyEofTrans() ) {
  748. out <<
  749. " if " << AT( ET(), vCS() ) << " > 0 then\n"
  750. " begin\n"
  751. " state.trans <- " << CAST(transType) << "(" << AT( ET(), vCS() ) << " - 1);\n"
  752. " raise Goto_eof_trans;\n"
  753. " end;\n";
  754. }
  755. if ( redFsm->anyEofActions() ) {
  756. out <<
  757. " let __acts = ref " << AT( EA(), vCS() ) << " in\n"
  758. " let __nacts = ref " << AT( A(), "!__acts" ) << " in\n"
  759. " incr __acts;\n"
  760. " while !__nacts > 0 do\n"
  761. " decr __nacts;\n"
  762. " begin match " << AT( A(), POST_INCR("__acts.contents") ) << " with\n";
  763. EOF_ACTION_SWITCH();
  764. SWITCH_DEFAULT() <<
  765. " end;\n"
  766. " done\n";
  767. }
  768. out <<
  769. " with Goto_again -> do_again ()\n"
  770. " | Goto_eof_trans -> do_eof_trans () end\n"
  771. "\n";
  772. }
  773. else
  774. {
  775. out << "\t()\n";
  776. }
  777. if ( outLabelUsed )
  778. out << " and do_out () = ()\n";
  779. out << "\tin do_start ()\n";
  780. out << " end;\n";
  781. }
  782. void OCamlFlatCodeGen::initVarTypes()
  783. {
  784. slenType = ARRAY_TYPE(MAX(redFsm->maxSpan, redFsm->maxCondSpan));
  785. transType = ARRAY_TYPE(redFsm->maxIndex+1);
  786. indsType = ARRAY_TYPE(redFsm->maxFlatIndexOffset);
  787. condsType = ARRAY_TYPE(redFsm->maxCondIndexOffset);
  788. }