亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? codegen.cpp

?? 這是一些于C++做的經典例子
?? CPP
字號:
#include "SCC.H"
#include "CodeGen.H"
#include "PTNode.H"


CodeGen::CodeGen()
{
  // When this class is instantiated, open the 'out.bin' file.  Obviously, a
  // real compiler would want the user to specify the output file name as a
  // command-line argument.
  out = fopen( "out.bin", "wb" );
  if ( out == NULL ) {
    perror( "out.bin" );
    exit( 1 );
  }
}


CodeGen::~CodeGen()
{
  // Make sure to close the bytecode stream.
  fclose( out );
}


void
CodeGen::StartGen( PTNodePtr root )
{
  // Before we can start generating the code in the script, we have to
  // allocate space for any variables that are used in the script.  Since the
  // interpreter does not support scopes, all the variables exist at the base
  // of the stack.  Iterate through the entire symbol table and allocate space
  // for them on the stack.
  //
  // While we are doing this, we need to also need to set the variables
  // address.  This will be important later when the variable is actually
  // used.
  SymbolTable::iterator i = symtbl.begin();
  SymbolTable::iterator end = symtbl.end();

  unsigned int offset = 0;

  for ( ; i != end; ++i ) {
    IdentifierNodePtr var = (*i).second;

    // The interpreter expects the variable offsets to be in word entries;
    // therefore, we only need to increment the offset by one for each
    // variable.
    var->SetOffset( offset );
    ++offset;

    // Emit a dummy push instruction.  This allocates space for the variable
    // on the stack.
    WriteOpcode( Push_Opcode );
    WriteArg( 0 );
  }

  // Now that space for all the variables have been allocated and their
  // offsets are set, generate the script's code.
  Gen( root );

  // To be clean, emit pop instructions to remove the variables that we
  // previously added to the stack.  This will ensure that the stack starts
  // and stops empty.
  for ( i = symtbl.begin(); i != end; ++i )
    WriteOpcode( Pop_Opcode );
}


size_t
CodeGen::Gen( PTNodePtr node )
{
  // This function switches on the node's type and passes flow of control off
  // to the proper internal code generator function.  This helper function
  // will recursively call this function for any children that it may have.

  // It is useful for some of the opcode generators to know how much code has
  // been generated.  Store a marker here when before we generate anything so
  // we can figure out how many bytes was generated for this node.
  Marker start = GetCurrentMarker();

  switch ( node->GetType() ) {
    case Add_PTNodeType:
      GenAdd( AddNodePtr( node ) );
      break;

    case Subtract_PTNodeType:
      GenSubtract( SubtractNodePtr( node ) );
      break;

    case Multiply_PTNodeType:
      GenMultiply( MultiplyNodePtr( node ) );
      break;

    case Divide_PTNodeType:
      GenDivide( DivideNodePtr( node ) );
      break;

    case Constant_PTNodeType:
      GenConstant( ConstantNodePtr( node ) );
      break;

    case Identifier_PTNodeType:
      GenIdentifier( IdentifierNodePtr( node ) );
      break;

    case Assignment_PTNodeType:
      GenAssignment( AssignmentNodePtr( node ) );
      break;

    case If_PTNodeType:
      GenIf( IfNodePtr( node ) );
      break;

    case Statement_PTNodeType:
      GenStatement( StatementNodePtr( node ) );
      break;

    case Block_PTNodeType:
      GenBlock( BlockNodePtr( node ) );
      break;

    default:
      // Some unknown node type!  This shouldn't happen...
      assert( false );
      break;
  }

  return GetCurrentMarker() - start;
}


void
CodeGen::GenAdd( AddNodePtr add )
{
  // All of the basic math nodes have the same format:  Generate the code for
  // the left & right hand expressions, and then emit the proper opcode
  // instruction.  This makes sure that the stack will contain the proper two
  // values to preform the addition, subtraction, etc.
  Gen( add->GetLHS() );
  Gen( add->GetRHS() );

  WriteOpcode( Add_Opcode );
}


void
CodeGen::GenSubtract( SubtractNodePtr subtract )
{
  Gen( subtract->GetLHS() );
  Gen( subtract->GetRHS() );

  WriteOpcode( Subtract_Opcode );
}


void
CodeGen::GenMultiply( MultiplyNodePtr multiply )
{
  Gen( multiply->GetLHS() );
  Gen( multiply->GetRHS() );

  WriteOpcode( Multiply_Opcode );
}


void
CodeGen::GenDivide( DivideNodePtr divide )
{
  Gen( divide->GetLHS() );
  Gen( divide->GetRHS() );

  WriteOpcode( Divide_Opcode );
}


void
CodeGen::GenConstant( ConstantNodePtr constant )
{
  // A constant simply pushes its own value onto the stack.  The Push opcode
  // expects that the next word in the bytecode stream is the value to push
  // onto the stack.
  WriteOpcode( Push_Opcode );
  WriteArg( constant->GetValue() );
}


void
CodeGen::GenIdentifier( IdentifierNodePtr identifier )
{
  // An identifier node simply refers that the variable is being "used".  This
  // means its current value should be pushed onto the stack.
  WriteOpcode( Load_Opcode );
  WriteArg( identifier->GetOffset() );
}


void
CodeGen::GenAssignment( AssignmentNodePtr assignment )
{
  Gen( assignment->GetRHS() );

  // An assigment is an expression not a statement.  It needs to leave the
  // result of the assignment on the stack.  This allows the script writer to
  // chain assignments such as:  a = b = 5;
  WriteOpcode( Dupe_Opcode );

  // The left hand side of the assignment node will always be the variable to
  // assign to.  This node's code isn't emited directly.  It is only used to
  // fetch the proper variable offset for the store opcode.
  IdentifierNodePtr var = IdentifierNodePtr( assignment->GetLHS() );

  WriteOpcode( Store_Opcode );
  WriteArg( var->GetOffset() );
}


void
CodeGen::GenIf( IfNodePtr ifNode )
{
  // The assembly for an if-statement with an else block will look like:
  //
  //     Perform the conditional instructions.
  //     If top-stack element is zero, Jump to label A.
  //     Perform true statements.
  //     Jump to label B.
  // A:  Preform false statements.
  // B:
  //
  // The last label, B, will actually point to the next instruction after
  // the if.  An if-statement with out an else block is slightly simplier, it
  // looks like:
  //
  //     Perform the conditional instructions.
  //     If top-stack element is zero, Jump to label A.
  //     Perform true statements.
  // A:
  //
  // Note that the first assembly block will work for both forms of an if
  // statement; however, the second form is slightly more efficient for
  // if-statements with out a false block (it doesn't need the "Jump to B"
  // instruction).


  Marker ifArg;
  size_t trueSize;

  // Generate the if-statement's conditional.  This will leave an argument on
  // the stack that can be used by the IfZero opcode.
  Gen( ifNode->GetConditional() );

  // Emit the IfZero opcode.  If the value on the stack is false, then this
  // opcode will jump to the false statements of the if.  Since the size of
  // the true block isn't known, save a marker so the value can be filled in
  // later.
  WriteOpcode( IfZero_Opcode );
  ifArg = WriteArg( 0 );

  // Generate all of the true statements, and save their size.
  trueSize = Gen( ifNode->GetTrueStatements() );

  // If this if-statement contains any false statements, then emit their code.
  if ( ifNode->GetFalseStatements() != NULL ) {
    Marker jumpArg;
    size_t falseSize;

    // Before the false statements, a relative jump is required to skip these
    // false statements.  This jump is considered part of the true block, and
    // the true statement's size needs to be updated accordingly.
    WriteOpcode( Jump_Opcode );
    jumpArg = WriteArg( 0 );

    trueSize += sizeof( Opcode );
    trueSize += sizeof( int );

    // Generate the if-statements, and update the Jump opcode's argument since
    // we now know how many bytes it needs to skip.
    falseSize = Gen( ifNode->GetFalseStatements() );
    UpdateArg( jumpArg, falseSize );
  }

  // Now that the finial size of the true statement block is known, update
  // IfZero's argument.
  UpdateArg( ifArg, trueSize );
}


void
CodeGen::GenFor( ForNodePtr forStmt )
{
  // The assembly for a for-statement looks like:
  //
  //     Perform pre-loop expression.
  // A:  Perform loop conditional expression.
  //     Jump to label B if top-stack element is zero.
  //     Perform loop body statements.
  //     Perform loop incremental expression.
  //     Jump to label A.
  // B:
  //
  // The last label, B, will actually point to the next isntruction after the
  // for.

  Marker loopTop;
  Marker loopSize;
  Marker ifArg;
  Marker jumpArg;

  // Generate the code for the preloop expression.  Nothing special needs to
  // happen here.
  Gen( forStmt->GetPreLoop() );

  // Save a marker to the top of the loop.  This will be needed to calculate
  // the size of the loop body.
  loopTop = GetCurrentMarker();

  // Generate the conditional part of the for-loop.  Note that we have to
  // generate the IfZero opcodes to actually test the conditional and jump out
  // of the loop, if needed.
  Gen( forStmt->GetConditional() );
  WriteOpcode( IfZero_Opcode );
  ifArg = WriteArg( 0 );

  // Generate the code for the inner part of the function loop (this includes
  // the incremental expression).
  Gen( forStmt->GetLoopBody() );
  Gen( forStmt->GetPostLoop() );

  // Generate the code to jump back up to the conditional.
  WriteOpcode( Jump_Opcode );
  jumpArg = WriteArg( 0 );

  // Now that the entire body of the loop has been generated, calculate the
  // size of the loop body so we can update the jump values.  Note that the
  // jump at the end of the loop needs to go backwards (hence the negative).
  loopSize = GetCurrentMarker() - loopTop;

  UpdateArg( ifArg, loopSize );
  UpdateArg( jumpArg, -loopSize );
}


void
CodeGen::GenStatement( StatementNodePtr stmt )
{
  // A statement yields its entire work to its expression; however, this
  // expression will leave a value on the stack.  For example, the expression
  // "4+5" will leave the answer "9" as the top-most stack element.  Since
  // this statemnt has been completed, it is save to pop this element off the
  // stack.  It is no longer needed.
  //
  // HOWEVER, a statement with no expression does not generate any code (since
  // there is nothing to pop off).  This makes it easy to support empty
  // statements (most notiably for a for-loop).
  if ( stmt == NULL )
    return;

  Gen( stmt->GetExpression() );

  WriteOpcode( Pop_Opcode );
}


void
CodeGen::GenBlock( BlockNodePtr block )
{
  // Block nodes do not have any code to generate.  They simply iterate over
  // all their children making sure that their values are generated.
  NodeList::const_iterator i = block->GetChildrenBegin();
  NodeList::const_iterator end = block->GetChildrenEnd();

  for ( ; i != end; ++i ) {
    const PTNodePtr node = *i;

    Gen( node );
  }
}


void
CodeGen::WriteOpcode( Opcode op )
{
  // Write out opcodes as if they were an integer.  If the size of the
  // generate bytecode stream is an issue, then you'll want to only
  // write out the smallest amount possible (probably a byte).
  WriteArg( (int)op );
}


CodeGen::Marker
CodeGen::WriteArg( int arg )
{
  // In case the code generator needs to update this opcode argument, return
  // this argument's marker.  We have to fetch the marker now before we update
  // the output file since the marker is supposed to point to the beginning of
  // the argument.
  Marker pos = GetCurrentMarker();

  // Some opcodes (such as Push) expect an argument from the bytecode stream.
  // This function writes out such and argument to the output file.
  fwrite( &arg, sizeof( arg ), 1, out );

  return pos;
}


void
CodeGen::UpdateArg( Marker pos, int arg )
{
  // The marker is really just a file position, so rewind back to the file
  // position, write the new argument, and zip back to the end of the file.
  fseek( out, pos, SEEK_SET );
  WriteArg( arg );
  fseek( out, 0, SEEK_END );
}


CodeGen::Marker
CodeGen::GetCurrentMarker()
{
  // Just use the current offset in the output file as the marker.
  return ftell( out );
}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
日本一区二区三区高清不卡| av中文字幕亚洲| 亚洲成a人片在线观看中文| 欧美国产精品久久| 国产亚洲短视频| 日本一区二区高清| 亚洲国产精品精华液2区45| 国产欧美精品一区| 亚洲图片另类小说| 一区二区高清免费观看影视大全 | 欧美色老头old∨ideo| 欧洲av在线精品| 欧美日韩一区二区电影| 欧美精选一区二区| 日韩美女在线视频| 国产日韩在线不卡| 亚洲男女毛片无遮挡| 亚洲成人免费视| 九九热在线视频观看这里只有精品| 麻豆成人在线观看| 国产大片一区二区| 91亚洲精品久久久蜜桃| 欧美日本国产一区| 精品国产髙清在线看国产毛片| 国产亚洲精品超碰| 亚洲国产日韩在线一区模特| 日韩av网站免费在线| 岛国av在线一区| 欧美日韩一本到| 久久精品一区二区| 亚洲特黄一级片| 九九视频精品免费| 日本韩国欧美一区二区三区| 欧美电视剧免费全集观看| 国产精品久久久久久久岛一牛影视| 亚洲夂夂婷婷色拍ww47| 国产jizzjizz一区二区| 欧美熟乱第一页| 国产色综合久久| 日韩电影在线一区二区| 成人午夜电影网站| 日韩视频免费观看高清在线视频| 国产精品女同互慰在线看| 日本欧美韩国一区三区| 99精品1区2区| 欧美精品一区二区三区在线| 亚洲一区在线观看免费观看电影高清| 国产一区不卡精品| 在线电影国产精品| 亚洲男人的天堂在线aⅴ视频| 极品少妇xxxx精品少妇| 欧美日韩dvd在线观看| 亚洲欧洲日韩一区二区三区| 久久成人免费网| 欧美乱妇20p| 亚洲一区二区三区视频在线| www.欧美色图| 国产日韩视频一区二区三区| 日本少妇一区二区| 欧美日韩免费观看一区三区| 曰韩精品一区二区| 成人av电影在线| 久久精品一区二区三区四区| 国内外精品视频| 日韩欧美高清一区| 日本在线不卡一区| 911精品国产一区二区在线| 依依成人精品视频| 色狠狠综合天天综合综合| 国产精品免费久久| 成人av电影观看| **欧美大码日韩| 91啦中文在线观看| 亚洲精品高清在线| 欧美性受xxxx黑人xyx性爽| 亚洲精品高清视频在线观看| 91社区在线播放| 一级女性全黄久久生活片免费| 91免费看片在线观看| 《视频一区视频二区| 在线观看视频一区二区| 亚洲一二三区不卡| 欧美日产在线观看| 另类调教123区| 国产亚洲福利社区一区| av一区二区三区| 玉足女爽爽91| 精品国产一区二区在线观看| 韩国成人福利片在线播放| 欧美国产禁国产网站cc| 99riav一区二区三区| 亚洲最新视频在线观看| 69堂国产成人免费视频| 美女视频黄久久| 中文字幕精品三区| 91成人网在线| 理论片日本一区| 国产精品女同一区二区三区| 欧美日韩免费一区二区三区| 精品在线一区二区三区| 国产欧美日韩不卡| 色综合欧美在线视频区| 日韩av一级片| 欧美国产欧美亚州国产日韩mv天天看完整| 色婷婷一区二区| 久久电影网站中文字幕| 亚洲精品亚洲人成人网| 欧美一区二区三区四区在线观看 | 91精品国产福利| 国产一区二区三区免费在线观看| 国产精品国产a| 欧美剧情片在线观看| 国产成人亚洲精品青草天美| 一区二区三区精品| 久久综合狠狠综合久久综合88 | 欧美一区二区免费| 成人激情校园春色| 日韩vs国产vs欧美| 国产精品第一页第二页第三页| 欧美日韩国产精选| 99精品一区二区三区| 老司机午夜精品| 亚洲国产精品一区二区www在线| 久久精品亚洲国产奇米99| 欧美日韩高清影院| 不卡av免费在线观看| 极品少妇xxxx偷拍精品少妇| 亚洲国产精品精华液网站 | 欧美在线短视频| 国产福利91精品一区二区三区| 天堂一区二区在线| 亚洲色图欧洲色图婷婷| 国产调教视频一区| 久久伊人中文字幕| 日韩一区二区三区四区| 在线视频观看一区| 97久久超碰国产精品电影| 国产剧情av麻豆香蕉精品| 蜜臂av日日欢夜夜爽一区| 亚洲一区二区三区美女| 一区二区在线观看不卡| 1000部国产精品成人观看| 日本一区二区三区国色天香| 久久久久久黄色| 精品第一国产综合精品aⅴ| 91精品国产综合久久久久| 欧美日韩免费一区二区三区| 欧美性猛交xxxxxxxx| 日本二三区不卡| 在线观看日产精品| 欧美色网站导航| 欧美日韩午夜精品| 91精品在线免费观看| 欧美精品九九99久久| 在线电影国产精品| 欧美mv和日韩mv国产网站| 欧美不卡一区二区| 国产亚洲一区字幕| 国产欧美一区二区精品性色| 国产亚洲欧美中文| 中国色在线观看另类| 亚洲人妖av一区二区| 亚洲视频一二三区| 亚洲已满18点击进入久久| 五月天国产精品| 九色综合狠狠综合久久| 国产黄色91视频| 94色蜜桃网一区二区三区| 91久久久免费一区二区| 欧美视频一区二区三区在线观看 | 日韩美女视频一区二区在线观看| 日韩三级中文字幕| 亚洲国产精品99久久久久久久久| 日韩一区在线播放| 天堂精品中文字幕在线| 精品在线播放免费| 成人免费观看男女羞羞视频| 91久久香蕉国产日韩欧美9色| 欧美一区二区三区免费大片| 国产日韩精品久久久| 亚洲日本丝袜连裤袜办公室| 亚洲第一精品在线| 精品一区二区三区影院在线午夜 | 国产+成+人+亚洲欧洲自线| 成人app网站| 宅男噜噜噜66一区二区66| 亚洲国产成人一区二区三区| 亚洲一区二区三区国产| 国产黄色91视频| 欧美一区二区三区免费在线看| 国产精品天干天干在线综合| 婷婷久久综合九色综合绿巨人| 国产成人综合自拍| 欧美日免费三级在线| 国产日产亚洲精品系列| 亚洲第一二三四区| 成人永久aaa| 精品免费日韩av| 亚洲电影第三页| 91在线视频免费观看|