"Fossies" - the Fresh Open Source Software Archive

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


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

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