gocodegen.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. /*
  2. * Copyright 2001-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 "gocodegen.h"
  23. #include "ragel.h"
  24. #include "redfsm.h"
  25. #include "gendata.h"
  26. #include <sstream>
  27. #include <string>
  28. #include <assert.h>
  29. using std::ostream;
  30. using std::ostringstream;
  31. using std::string;
  32. using std::cerr;
  33. using std::endl;
  34. using std::istream;
  35. using std::ifstream;
  36. using std::ostream;
  37. using std::ios;
  38. using std::cin;
  39. using std::cout;
  40. using std::cerr;
  41. using std::endl;
  42. /*
  43. * Go Specific
  44. */
  45. void goLineDirective( ostream &out, const char *fileName, int line )
  46. {
  47. out << "//line " << fileName << ":" << line << endl;
  48. }
  49. void GoCodeGen::genLineDirective( ostream &out )
  50. {
  51. std::streambuf *sbuf = out.rdbuf();
  52. output_filter *filter = static_cast<output_filter*>(sbuf);
  53. goLineDirective( out, filter->fileName, filter->line + 1 );
  54. }
  55. unsigned int GoCodeGen::arrayTypeSize( unsigned long maxVal )
  56. {
  57. long long maxValLL = (long long) maxVal;
  58. HostType *arrayType = keyOps->typeSubsumes( maxValLL );
  59. assert( arrayType != 0 );
  60. return arrayType->size;
  61. }
  62. string GoCodeGen::ARRAY_TYPE( unsigned long maxVal )
  63. {
  64. long long maxValLL = (long long) maxVal;
  65. HostType *arrayType = keyOps->typeSubsumes( maxValLL );
  66. assert( arrayType != 0 );
  67. string ret = arrayType->data1;
  68. if ( arrayType->data2 != 0 ) {
  69. ret += " ";
  70. ret += arrayType->data2;
  71. }
  72. return ret;
  73. }
  74. /* Write out the fsm name. */
  75. string GoCodeGen::FSM_NAME()
  76. {
  77. return fsmName;
  78. }
  79. /* Emit the offset of the start state as a decimal integer. */
  80. string GoCodeGen::START_STATE_ID()
  81. {
  82. ostringstream ret;
  83. ret << redFsm->startState->id;
  84. return ret.str();
  85. };
  86. /* Write out the array of actions. */
  87. std::ostream &GoCodeGen::ACTIONS_ARRAY()
  88. {
  89. out << " 0, ";
  90. int totalActions = 1;
  91. for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
  92. /* Write out the length, which will never be the last character. */
  93. out << act->key.length() << ", ";
  94. if ( totalActions++ % IALL == 0 )
  95. out << endl << " ";
  96. for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) {
  97. out << item->value->actionId << ", ";
  98. if ( ! (act.last() && item.last()) ) {
  99. if ( totalActions++ % IALL == 0 )
  100. out << endl << " ";
  101. }
  102. }
  103. }
  104. out << endl;
  105. return out;
  106. }
  107. string GoCodeGen::ACCESS()
  108. {
  109. ostringstream ret;
  110. if ( accessExpr != 0 )
  111. INLINE_LIST( ret, accessExpr, 0, false, false );
  112. return ret.str();
  113. }
  114. string GoCodeGen::P()
  115. {
  116. ostringstream ret;
  117. if ( pExpr == 0 )
  118. ret << "p";
  119. else {
  120. ret << "(";
  121. INLINE_LIST( ret, pExpr, 0, false, false );
  122. ret << ")";
  123. }
  124. return ret.str();
  125. }
  126. string GoCodeGen::PE()
  127. {
  128. ostringstream ret;
  129. if ( peExpr == 0 )
  130. ret << "pe";
  131. else {
  132. ret << "(";
  133. INLINE_LIST( ret, peExpr, 0, false, false );
  134. ret << ")";
  135. }
  136. return ret.str();
  137. }
  138. string GoCodeGen::vEOF()
  139. {
  140. ostringstream ret;
  141. if ( eofExpr == 0 )
  142. ret << "eof";
  143. else {
  144. ret << "(";
  145. INLINE_LIST( ret, eofExpr, 0, false, false );
  146. ret << ")";
  147. }
  148. return ret.str();
  149. }
  150. string GoCodeGen::vCS()
  151. {
  152. ostringstream ret;
  153. if ( csExpr == 0 )
  154. ret << ACCESS() << "cs";
  155. else {
  156. /* Emit the user supplied method of retrieving the key. */
  157. ret << "(";
  158. INLINE_LIST( ret, csExpr, 0, false, false );
  159. ret << ")";
  160. }
  161. return ret.str();
  162. }
  163. string GoCodeGen::TOP()
  164. {
  165. ostringstream ret;
  166. if ( topExpr == 0 )
  167. ret << ACCESS() + "top";
  168. else {
  169. ret << "(";
  170. INLINE_LIST( ret, topExpr, 0, false, false );
  171. ret << ")";
  172. }
  173. return ret.str();
  174. }
  175. string GoCodeGen::STACK()
  176. {
  177. ostringstream ret;
  178. if ( stackExpr == 0 )
  179. ret << ACCESS() + "stack";
  180. else {
  181. ret << "(";
  182. INLINE_LIST( ret, stackExpr, 0, false, false );
  183. ret << ")";
  184. }
  185. return ret.str();
  186. }
  187. string GoCodeGen::ACT()
  188. {
  189. ostringstream ret;
  190. if ( actExpr == 0 )
  191. ret << ACCESS() + "act";
  192. else {
  193. ret << "(";
  194. INLINE_LIST( ret, actExpr, 0, false, false );
  195. ret << ")";
  196. }
  197. return ret.str();
  198. }
  199. string GoCodeGen::TOKSTART()
  200. {
  201. ostringstream ret;
  202. if ( tokstartExpr == 0 )
  203. ret << ACCESS() + "ts";
  204. else {
  205. ret << "(";
  206. INLINE_LIST( ret, tokstartExpr, 0, false, false );
  207. ret << ")";
  208. }
  209. return ret.str();
  210. }
  211. string GoCodeGen::TOKEND()
  212. {
  213. ostringstream ret;
  214. if ( tokendExpr == 0 )
  215. ret << ACCESS() + "te";
  216. else {
  217. ret << "(";
  218. INLINE_LIST( ret, tokendExpr, 0, false, false );
  219. ret << ")";
  220. }
  221. return ret.str();
  222. }
  223. string GoCodeGen::GET_WIDE_KEY()
  224. {
  225. if ( redFsm->anyConditions() )
  226. return "_widec";
  227. else
  228. return GET_KEY();
  229. }
  230. string GoCodeGen::GET_WIDE_KEY( RedStateAp *state )
  231. {
  232. if ( state->stateCondList.length() > 0 )
  233. return "_widec";
  234. else
  235. return GET_KEY();
  236. }
  237. string GoCodeGen::GET_KEY()
  238. {
  239. ostringstream ret;
  240. if ( getKeyExpr != 0 ) {
  241. /* Emit the user supplied method of retrieving the key. */
  242. ret << "(";
  243. INLINE_LIST( ret, getKeyExpr, 0, false, false );
  244. ret << ")";
  245. }
  246. else {
  247. /* Expression for retrieving the key, use simple dereference. */
  248. ret << DATA() << "[" << P() << "]";
  249. }
  250. return ret.str();
  251. }
  252. /* Write out level number of tabs. Makes the nested binary search nice
  253. * looking. */
  254. string GoCodeGen::TABS( int level )
  255. {
  256. string result;
  257. while ( level-- > 0 )
  258. result += "\t";
  259. return result;
  260. }
  261. /* Write out a key from the fsm code gen. Depends on wether or not the key is
  262. * signed. */
  263. string GoCodeGen::KEY( Key key )
  264. {
  265. ostringstream ret;
  266. if ( keyOps->isSigned || !hostLang->explicitUnsigned )
  267. ret << key.getVal();
  268. else
  269. ret << (unsigned long) key.getVal() << 'u';
  270. return ret.str();
  271. }
  272. bool GoCodeGen::isAlphTypeSigned()
  273. {
  274. return keyOps->isSigned;
  275. }
  276. bool GoCodeGen::isWideAlphTypeSigned()
  277. {
  278. string ret;
  279. if ( redFsm->maxKey <= keyOps->maxKey )
  280. return isAlphTypeSigned();
  281. else {
  282. long long maxKeyVal = redFsm->maxKey.getLongLong();
  283. HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
  284. return wideType->isSigned;
  285. }
  286. }
  287. string GoCodeGen::WIDE_KEY( RedStateAp *state, Key key )
  288. {
  289. if ( state->stateCondList.length() > 0 ) {
  290. ostringstream ret;
  291. if ( isWideAlphTypeSigned() )
  292. ret << key.getVal();
  293. else
  294. ret << (unsigned long) key.getVal() << 'u';
  295. return ret.str();
  296. }
  297. else {
  298. return KEY( key );
  299. }
  300. }
  301. void GoCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish )
  302. {
  303. /* The parser gives fexec two children. The double brackets are for D
  304. * code. If the inline list is a single word it will get interpreted as a
  305. * C-style cast by the D compiler. */
  306. ret << P() << " = (";
  307. INLINE_LIST( ret, item->children, targState, inFinish, false );
  308. ret << ") - 1" << endl;
  309. }
  310. void GoCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item,
  311. int targState, int inFinish, bool csForced )
  312. {
  313. ret <<
  314. " switch " << ACT() << " {" << endl;
  315. for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
  316. /* Write the case label, the action and the case break. */
  317. if ( lma->lmId < 0 ) {
  318. ret << " default:" << endl;
  319. }
  320. else
  321. ret << " case " << lma->lmId << ":" << endl;
  322. /* Write the block and close it off. */
  323. ret << " {";
  324. INLINE_LIST( ret, lma->children, targState, inFinish, csForced );
  325. ret << "}" << endl;
  326. }
  327. ret <<
  328. " }" << endl <<
  329. " ";
  330. }
  331. void GoCodeGen::SET_ACT( ostream &ret, GenInlineItem *item )
  332. {
  333. ret << ACT() << " = " << item->lmId << ";";
  334. }
  335. void GoCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item )
  336. {
  337. /* The tokend action sets tokend. */
  338. ret << TOKEND() << " = " << P();
  339. if ( item->offset != 0 )
  340. out << "+" << item->offset;
  341. out << endl;
  342. }
  343. void GoCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item )
  344. {
  345. ret << TOKEND();
  346. }
  347. void GoCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item )
  348. {
  349. ret << TOKSTART() << " = " << NULL_ITEM() << endl;
  350. }
  351. void GoCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item )
  352. {
  353. ret << ACT() << " = 0" << endl;
  354. }
  355. void GoCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item )
  356. {
  357. ret << TOKSTART() << " = " << P() << endl;
  358. }
  359. void GoCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item,
  360. int targState, bool inFinish, bool csForced )
  361. {
  362. if ( item->children->length() > 0 ) {
  363. /* Write the block and close it off. */
  364. ret << "{";
  365. INLINE_LIST( ret, item->children, targState, inFinish, csForced );
  366. ret << "}";
  367. }
  368. }
  369. /* Write out an inline tree structure. Walks the list and possibly calls out
  370. * to virtual functions than handle language specific items in the tree. */
  371. void GoCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList,
  372. int targState, bool inFinish, bool csForced )
  373. {
  374. for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
  375. switch ( item->type ) {
  376. case GenInlineItem::Text:
  377. ret << item->data;
  378. break;
  379. case GenInlineItem::Goto:
  380. GOTO( ret, item->targState->id, inFinish );
  381. break;
  382. case GenInlineItem::Call:
  383. CALL( ret, item->targState->id, targState, inFinish );
  384. break;
  385. case GenInlineItem::Next:
  386. NEXT( ret, item->targState->id, inFinish );
  387. break;
  388. case GenInlineItem::Ret:
  389. RET( ret, inFinish );
  390. break;
  391. case GenInlineItem::PChar:
  392. ret << P();
  393. break;
  394. case GenInlineItem::Char:
  395. ret << GET_KEY();
  396. break;
  397. case GenInlineItem::Hold:
  398. ret << P() << "--" << endl;
  399. break;
  400. case GenInlineItem::Exec:
  401. EXEC( ret, item, targState, inFinish );
  402. break;
  403. case GenInlineItem::Curs:
  404. CURS( ret, inFinish );
  405. break;
  406. case GenInlineItem::Targs:
  407. TARGS( ret, inFinish, targState );
  408. break;
  409. case GenInlineItem::Entry:
  410. ret << item->targState->id;
  411. break;
  412. case GenInlineItem::GotoExpr:
  413. GOTO_EXPR( ret, item, inFinish );
  414. break;
  415. case GenInlineItem::CallExpr:
  416. CALL_EXPR( ret, item, targState, inFinish );
  417. break;
  418. case GenInlineItem::NextExpr:
  419. NEXT_EXPR( ret, item, inFinish );
  420. break;
  421. case GenInlineItem::LmSwitch:
  422. LM_SWITCH( ret, item, targState, inFinish, csForced );
  423. break;
  424. case GenInlineItem::LmSetActId:
  425. SET_ACT( ret, item );
  426. break;
  427. case GenInlineItem::LmSetTokEnd:
  428. SET_TOKEND( ret, item );
  429. break;
  430. case GenInlineItem::LmGetTokEnd:
  431. GET_TOKEND( ret, item );
  432. break;
  433. case GenInlineItem::LmInitTokStart:
  434. INIT_TOKSTART( ret, item );
  435. break;
  436. case GenInlineItem::LmInitAct:
  437. INIT_ACT( ret, item );
  438. break;
  439. case GenInlineItem::LmSetTokStart:
  440. SET_TOKSTART( ret, item );
  441. break;
  442. case GenInlineItem::SubAction:
  443. SUB_ACTION( ret, item, targState, inFinish, csForced );
  444. break;
  445. case GenInlineItem::Break:
  446. BREAK( ret, targState, csForced );
  447. break;
  448. }
  449. }
  450. }
  451. /* Write out paths in line directives. Escapes any special characters. */
  452. string GoCodeGen::LDIR_PATH( char *path )
  453. {
  454. ostringstream ret;
  455. for ( char *pc = path; *pc != 0; pc++ ) {
  456. if ( *pc == '\\' )
  457. ret << "\\\\";
  458. else
  459. ret << *pc;
  460. }
  461. return ret.str();
  462. }
  463. void GoCodeGen::ACTION( ostream &ret, GenAction *action, int targState,
  464. bool inFinish, bool csForced )
  465. {
  466. /* Write the preprocessor line info for going into the source file. */
  467. goLineDirective( ret, action->loc.fileName, action->loc.line );
  468. /* Write the block and close it off. */
  469. INLINE_LIST( ret, action->inlineList, targState, inFinish, csForced );
  470. ret << endl;
  471. }
  472. void GoCodeGen::CONDITION( ostream &ret, GenAction *condition )
  473. {
  474. INLINE_LIST( ret, condition->inlineList, 0, false, false );
  475. }
  476. string GoCodeGen::ERROR_STATE()
  477. {
  478. ostringstream ret;
  479. if ( redFsm->errState != 0 )
  480. ret << redFsm->errState->id;
  481. else
  482. ret << "-1";
  483. return ret.str();
  484. }
  485. string GoCodeGen::FIRST_FINAL_STATE()
  486. {
  487. ostringstream ret;
  488. if ( redFsm->firstFinState != 0 )
  489. ret << redFsm->firstFinState->id;
  490. else
  491. ret << redFsm->nextStateId;
  492. return ret.str();
  493. }
  494. void GoCodeGen::writeInit()
  495. {
  496. out << " {" << endl;
  497. if ( !noCS )
  498. out << " " << vCS() << " = " << START() << endl;
  499. /* If there are any calls, then the stack top needs initialization. */
  500. if ( redFsm->anyActionCalls() || redFsm->anyActionRets() )
  501. out << " " << TOP() << " = 0" << endl;
  502. if ( hasLongestMatch ) {
  503. out <<
  504. " " << TOKSTART() << " = " << NULL_ITEM() << endl <<
  505. " " << TOKEND() << " = " << NULL_ITEM() << endl <<
  506. " " << ACT() << " = 0" << endl;
  507. }
  508. out << " }" << endl;
  509. }
  510. string GoCodeGen::DATA()
  511. {
  512. ostringstream ret;
  513. if ( dataExpr == 0 )
  514. ret << ACCESS() + "data";
  515. else {
  516. ret << "(";
  517. INLINE_LIST( ret, dataExpr, 0, false, false );
  518. ret << ")";
  519. }
  520. return ret.str();
  521. }
  522. string GoCodeGen::DATA_PREFIX()
  523. {
  524. if ( !noPrefix )
  525. return FSM_NAME() + "_";
  526. return "";
  527. }
  528. /* Emit the alphabet data type. */
  529. string GoCodeGen::ALPH_TYPE()
  530. {
  531. string ret = keyOps->alphType->data1;
  532. if ( keyOps->alphType->data2 != 0 ) {
  533. ret += " ";
  534. ret += + keyOps->alphType->data2;
  535. }
  536. return ret;
  537. }
  538. /* Emit the alphabet data type. */
  539. string GoCodeGen::WIDE_ALPH_TYPE()
  540. {
  541. string ret;
  542. if ( redFsm->maxKey <= keyOps->maxKey )
  543. ret = ALPH_TYPE();
  544. else {
  545. long long maxKeyVal = redFsm->maxKey.getLongLong();
  546. HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
  547. assert( wideType != 0 );
  548. ret = wideType->data1;
  549. if ( wideType->data2 != 0 ) {
  550. ret += " ";
  551. ret += wideType->data2;
  552. }
  553. }
  554. return ret;
  555. }
  556. void GoCodeGen::STATE_IDS()
  557. {
  558. if ( redFsm->startState != 0 )
  559. CONST( "int", START() ) << " = " << START_STATE_ID() << endl;
  560. if ( !noFinal )
  561. CONST( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << endl;
  562. if ( !noError )
  563. CONST( "int", ERROR() ) << " = " << ERROR_STATE() << endl;
  564. out << endl;
  565. if ( !noEntry && entryPointNames.length() > 0 ) {
  566. for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) {
  567. CONST( "int", DATA_PREFIX() + "en_" + *en ) <<
  568. " = " << entryPointIds[en.pos()] << endl;
  569. }
  570. out << endl;
  571. }
  572. }
  573. void GoCodeGen::writeStart()
  574. {
  575. out << START_STATE_ID();
  576. }
  577. void GoCodeGen::writeFirstFinal()
  578. {
  579. out << FIRST_FINAL_STATE();
  580. }
  581. void GoCodeGen::writeError()
  582. {
  583. out << ERROR_STATE();
  584. }
  585. void GoCodeGen::finishRagelDef()
  586. {
  587. if ( codeStyle == GenGoto || codeStyle == GenFGoto ||
  588. codeStyle == GenIpGoto || codeStyle == GenSplit )
  589. {
  590. /* For directly executable machines there is no required state
  591. * ordering. Choose a depth-first ordering to increase the
  592. * potential for fall-throughs. */
  593. redFsm->depthFirstOrdering();
  594. }
  595. else {
  596. /* The frontend will do this for us, but it may be a good idea to
  597. * force it if the intermediate file is edited. */
  598. redFsm->sortByStateId();
  599. }
  600. /* Choose default transitions and the single transition. */
  601. redFsm->chooseDefaultSpan();
  602. /* Maybe do flat expand, otherwise choose single. */
  603. if ( codeStyle == GenFlat || codeStyle == GenFFlat )
  604. redFsm->makeFlat();
  605. else
  606. redFsm->chooseSingle();
  607. /* If any errors have occured in the input file then don't write anything. */
  608. if ( gblErrorCount > 0 )
  609. return;
  610. if ( codeStyle == GenSplit )
  611. redFsm->partitionFsm( numSplitPartitions );
  612. if ( codeStyle == GenIpGoto || codeStyle == GenSplit )
  613. redFsm->setInTrans();
  614. /* Anlayze Machine will find the final action reference counts, among
  615. * other things. We will use these in reporting the usage
  616. * of fsm directives in action code. */
  617. analyzeMachine();
  618. /* Determine if we should use indicies. */
  619. calcIndexSize();
  620. }
  621. ostream &GoCodeGen::source_warning( const InputLoc &loc )
  622. {
  623. cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
  624. return cerr;
  625. }
  626. ostream &GoCodeGen::source_error( const InputLoc &loc )
  627. {
  628. gblErrorCount += 1;
  629. assert( sourceFileName != 0 );
  630. cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
  631. return cerr;
  632. }
  633. /*
  634. * Go implementation.
  635. *
  636. */
  637. std::ostream &GoCodeGen::OPEN_ARRAY( string type, string name )
  638. {
  639. out << "var " << name << " []" << type << " = []" << type << "{" << endl;
  640. return out;
  641. }
  642. std::ostream &GoCodeGen::CLOSE_ARRAY()
  643. {
  644. return out << "}" << endl;
  645. }
  646. std::ostream &GoCodeGen::STATIC_VAR( string type, string name )
  647. {
  648. out << "var " << name << " " << type;
  649. return out;
  650. }
  651. std::ostream &GoCodeGen::CONST( string type, string name )
  652. {
  653. out << "const " << name << " " << type;
  654. return out;
  655. }
  656. string GoCodeGen::UINT( )
  657. {
  658. return "uint";
  659. }
  660. string GoCodeGen::INT()
  661. {
  662. return "int";
  663. }
  664. string GoCodeGen::CAST( string type, string expr )
  665. {
  666. return type + "(" + expr + ")";
  667. }
  668. string GoCodeGen::NULL_ITEM()
  669. {
  670. return "0";
  671. }
  672. void GoCodeGen::writeExports()
  673. {
  674. if ( exportList.length() > 0 ) {
  675. for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
  676. out << "const " << DATA_PREFIX() << "ex_" << ex->name << " = " <<
  677. KEY(ex->key) << endl;
  678. }
  679. out << endl;
  680. }
  681. }