📄 code_emit.cpp
字号:
pstrSourceLine [ iLastCharIndex ] = '\0';
// Emit the comment, but only prepend it with a line break if it's not the
// first one
if ( ! iIsFirstSourceLine )
fprintf ( g_pOutputFile, "\n" );
fprintf ( g_pOutputFile, "\t\t; %s\n\n", pstrSourceLine );
break;
}
// An I-code instruction
case ICODE_NODE_INSTR:
{
// Emit the opcode
fprintf ( g_pOutputFile, "\t\t%s", ppstrMnemonics [ pCurrNode->Instr.iOpcode ] );
// Determine the number of operands
int iOpCount = pCurrNode->Instr.OpList.iNodeCount;
// If there are operands to emit, follow the instruction with some space
if ( iOpCount )
{
// All instructions get at least one tab
fprintf ( g_pOutputFile, "\t" );
// If it's less than a tab stop's width in characters, however, they get a
// second
if ( strlen ( ppstrMnemonics [ pCurrNode->Instr.iOpcode ] ) < TAB_STOP_WIDTH )
fprintf ( g_pOutputFile, "\t" );
}
// Emit each operand
for ( int iCurrOpIndex = 0; iCurrOpIndex < iOpCount; ++ iCurrOpIndex )
{
// Get a pointer to the operand structure
Op * pOp = GetICodeOpByIndex ( pCurrNode, iCurrOpIndex );
// Emit the operand based on its type
switch ( pOp->iType )
{
// Integer literal
case OP_TYPE_INT:
fprintf ( g_pOutputFile, "%d", pOp->iIntLiteral );
break;
// Float literal
case OP_TYPE_FLOAT:
fprintf ( g_pOutputFile, "%f", pOp->fFloatLiteral );
break;
// String literal
case OP_TYPE_STRING_INDEX:
fprintf ( g_pOutputFile, "\"%s\"", GetStringByIndex ( & g_StringTable, pOp->iStringIndex ) );
break;
// Variable
case OP_TYPE_VAR:
fprintf ( g_pOutputFile, "%s", GetSymbolByIndex ( pOp->iSymbolIndex )->pstrIdent );
break;
// Array index absolute
case OP_TYPE_ARRAY_INDEX_ABS:
fprintf ( g_pOutputFile, "%s [ %d ]", GetSymbolByIndex ( pOp->iSymbolIndex )->pstrIdent,
pOp->iOffset );
break;
// Array index variable
case OP_TYPE_ARRAY_INDEX_VAR:
fprintf ( g_pOutputFile, "%s [ %s ]", GetSymbolByIndex ( pOp->iSymbolIndex )->pstrIdent,
GetSymbolByIndex ( pOp->iOffsetSymbolIndex )->pstrIdent );
break;
// Function
case OP_TYPE_FUNC_INDEX:
fprintf ( g_pOutputFile, "%s", GetFuncByIndex ( pOp->iSymbolIndex )->pstrName );
break;
// Register (just _RetVal for now)
case OP_TYPE_REG:
fprintf ( g_pOutputFile, "_RetVal" );
break;
// Jump target index
case OP_TYPE_JUMP_TARGET_INDEX:
fprintf ( g_pOutputFile, "_L%d", pOp->iJumpTargetIndex );
break;
}
// If the operand isn't the last one, append it with a comma and space
if ( iCurrOpIndex != iOpCount - 1 )
fprintf ( g_pOutputFile, ", " );
}
// Finish the line
fprintf ( g_pOutputFile, "\n" );
break;
}
// A jump target
case ICODE_NODE_JUMP_TARGET:
{
// Emit a label in the format _LX, where X is the jump target
fprintf ( g_pOutputFile, "\t_L%d:\n", pCurrNode->iJumpTargetIndex );
}
}
// Update the first line flag
if ( iIsFirstSourceLine )
iIsFirstSourceLine = FALSE;
}
}
else
{
// No, so emit a comment saying so
fprintf ( g_pOutputFile, "\t\t; (No code)\n" );
}
// Emit the closing brace
fprintf ( g_pOutputFile, "\t}" );
}
/******************************************************************************************
*
* EmitCode ()
*
* Translates the I-code representation of the script to an ASCII-foramtted XVM assembly
* file.
*/
void EmitCode ()
{
// ---- Open the output file
if ( ! ( g_pOutputFile = fopen ( g_pstrOutputFilename, "wb" ) ) )
ExitOnError ( "Could not open output file for output" );
// ---- Emit the header
EmitHeader ();
// ---- Emit directives
fprintf ( g_pOutputFile, "; ---- Directives -----------------------------------------------------------------------------\n\n" );
EmitDirectives ();
// ---- Emit global variable declarations
fprintf ( g_pOutputFile, "; ---- Global Variables -----------------------------------------------------------------------\n\n" );
// Emit the globals by printing all non-parameter symbols in the global scope
EmitScopeSymbols ( SCOPE_GLOBAL, SYMBOL_TYPE_VAR );
// ---- Emit functions
fprintf ( g_pOutputFile, "; ---- Functions ------------------------------------------------------------------------------\n\n" );
// Local node for traversing lists
LinkedListNode * pNode = g_FuncTable.pHead;
// Local function node pointer
FuncNode * pCurrFunc;
// Pointer to hold the _Main () function, if it's found
FuncNode * pMainFunc = NULL;
// Loop through each function and emit its declaration and code, if functions exist
if ( g_FuncTable.iNodeCount > 0 )
{
while ( TRUE )
{
// Get a pointer to the node
pCurrFunc = ( FuncNode * ) pNode->pData;
// Don't emit host API function nodes
if ( ! pCurrFunc->iIsHostAPI )
{
// Is the current function _Main ()?
if ( stricmp ( pCurrFunc->pstrName, MAIN_FUNC_NAME ) == 0 )
{
// Yes, so save the pointer for later (and don't emit it yet)
pMainFunc = pCurrFunc;
}
else
{
// No, so emit it
EmitFunc ( pCurrFunc );
fprintf ( g_pOutputFile, "\n\n" );
}
}
// Move to the next node
pNode = pNode->pNext;
if ( ! pNode )
break;
}
}
// ---- Emit _Main ()
fprintf ( g_pOutputFile, "; ---- Main -----------------------------------------------------------------------------------" );
// If the last pass over the functions found a _Main () function. emit it
if ( pMainFunc )
{
fprintf ( g_pOutputFile, "\n\n" );
EmitFunc ( pMainFunc );
}
// ---- Close output file
fclose ( g_pOutputFile );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -