#include #include #include #include "Types.h" #include "utils/ByteCodePrinter.h" #define LINE_LENGTH 80 static ByteCode* code; static int readIndex; static int line; static char buffer[LINE_LENGTH]; static int bIndex; static void btPrintHeading() { puts("| Index | Line | Operation | Argument 1 | Argument 2 |"); puts("|--------|-------|----------------------|------------|------------|"); } static void btAdd(const char* format, ...) { va_list args; va_start(args, format); bIndex += vsnprintf(buffer + bIndex, LINE_LENGTH - bIndex, format, args); va_end(args); } static void btFillBase() { buffer[0] = '\0'; bIndex = 0; btAdd("| %6d | %5d |", readIndex - 1, line); } static void btRead(void* buffer, int length) { if(readIndex + length > code->length) { return; } memcpy(buffer, code->code + readIndex, length); readIndex += length; } static void btAddOperation(const char* s) { if(s[0] != '\0' && s[1] != '\0' && s[2] != '\0' && s[3] != '\0') { s += 3; } btAdd(" %20s |", s); } static void btAddInt32() { int32 value = 0; btRead(&value, sizeof(int32)); btAdd(" %10d |", value); } static void btAddInt64() { int64 value = 0; btRead(&value, sizeof(int64)); btAdd(" %10ld |", value); } static void btAddInt8() { int8 value = 0; btRead(&value, sizeof(int8)); btAdd(" %10d |", (int32)value); } static void btAddFloat() { float value = 0; btRead(&value, sizeof(float)); btAdd(" %10.2f |", value); } static void btAddFiller() { btAdd(" |"); } static void sPrintLine() { btRead(&line, 2); printf("| %6d |-------|----------------------|------------|------------|\n", readIndex - 3); } static void btPrintOp(const char* op) { btFillBase(); btAddOperation(op); btAddFiller(); btAddFiller(); puts(buffer); } static void btPrintInt32(const char* op) { btFillBase(); btAddOperation(op); btAddInt32(); btAddFiller(); puts(buffer); } static void btPrintInt64(const char* op) { btFillBase(); btAddOperation(op); btAddInt64(); btAddFiller(); puts(buffer); } static void btPrintInt8(const char* op) { btFillBase(); btAddOperation(op); btAddInt8(); btAddFiller(); puts(buffer); } static void btPrint2Int32(const char* op) { btFillBase(); btAddOperation(op); btAddInt32(); btAddInt32(); puts(buffer); } static void btPrintFloat(const char* op) { btFillBase(); btAddOperation(op); btAddFloat(); btAddFiller(); puts(buffer); } #define PRINT_OP_BASE(op, name) \ case op: \ btPrint##name(#op); \ break; #define PRINT_OP(op) PRINT_OP_BASE(op, Op) #define PRINT_OP_INT8(op) PRINT_OP_BASE(op, Int8) #define PRINT_OP_INT32(op) PRINT_OP_BASE(op, Int32) #define PRINT_OP_2INT32(op) PRINT_OP_BASE(op, 2Int32) #define PRINT_OP_INT64(op) PRINT_OP_BASE(op, Int64) #define PRINT_INTEGRAL_OP(op) \ PRINT_OP(OP_##op##_INT32) PRINT_OP(OP_##op##_INT64) #define PRINT_NUMBER_OP(op) PRINT_INTEGRAL_OP(op) PRINT_OP(OP_##op##_FLOAT) #define PRINT_TYPES(TYPE) \ PRINT_OP(OP_STORE_##TYPE); \ PRINT_OP(OP_LOAD_##TYPE); \ PRINT_OP_INT32(OP_RETURN_##TYPE); \ PRINT_OP(OP_EQUAL_##TYPE); \ PRINT_OP(OP_NOT_EQUAL_##TYPE); static void btConsumeOperation() { Operation op = code->code[readIndex++]; switch(op) { PRINT_TYPES(INT32); PRINT_TYPES(INT64); PRINT_TYPES(BOOL); PRINT_TYPES(FLOAT); PRINT_OP(OP_NOTHING); PRINT_OP_INT32(OP_PUSH_INT32); PRINT_OP_INT64(OP_PUSH_INT64); PRINT_OP_BASE(OP_PUSH_FLOAT, Float); PRINT_OP(OP_PUSH_TRUE); PRINT_OP(OP_PUSH_FALSE); PRINT_OP(OP_PUSH_NULLPTR); PRINT_NUMBER_OP(ADD); PRINT_NUMBER_OP(SUB); PRINT_NUMBER_OP(MUL); PRINT_NUMBER_OP(DIV); PRINT_INTEGRAL_OP(MOD); PRINT_NUMBER_OP(INVERT_SIGN); PRINT_NUMBER_OP(LESS); PRINT_NUMBER_OP(LESS_EQUAL); PRINT_NUMBER_OP(GREATER); PRINT_NUMBER_OP(GREATER_EQUAL); PRINT_OP(OP_NOT); PRINT_OP(OP_AND); PRINT_OP(OP_OR); PRINT_INTEGRAL_OP(BIT_NOT); PRINT_INTEGRAL_OP(BIT_AND); PRINT_INTEGRAL_OP(BIT_OR); PRINT_INTEGRAL_OP(BIT_XOR); PRINT_INTEGRAL_OP(LEFT_SHIFT); PRINT_INTEGRAL_OP(RIGHT_SHIFT); PRINT_OP_INT32(OP_GOTO); PRINT_OP_INT32(OP_IF_GOTO); PRINT_OP_INT32(OP_PEEK_FALSE_GOTO); PRINT_OP_INT32(OP_PEEK_TRUE_GOTO); PRINT_OP_2INT32(OP_GOSUB); PRINT_OP_INT32(OP_RETURN); PRINT_OP_INT32(OP_RETURN_POINTER); PRINT_OP_2INT32(OP_RESERVE); PRINT_OP_INT32(OP_DEREFERENCE_VAR); PRINT_OP(OP_REFERENCE); PRINT_OP(OP_DUPLICATE_REFERENCE); PRINT_OP_INT32(OP_ADD_REFERENCE); PRINT_OP_INT32(OP_NEW); PRINT_OP(OP_DELETE); PRINT_OP(OP_LENGTH); PRINT_OP_INT32(OP_LOAD); PRINT_OP(OP_STORE_POINTER); PRINT_OP(OP_EQUAL_POINTER); PRINT_OP(OP_NOT_EQUAL_POINTER); PRINT_OP_INT8(OP_PUSH_PRE_CHANGE_INT32); PRINT_OP_INT8(OP_PUSH_POST_CHANGE_INT32); PRINT_OP_INT8(OP_CHANGE_INT32); PRINT_OP_INT8(OP_PUSH_PRE_CHANGE_INT64); PRINT_OP_INT8(OP_PUSH_POST_CHANGE_INT64); PRINT_OP_INT8(OP_CHANGE_INT64); PRINT_OP(OP_INT32_TO_FLOAT); PRINT_OP(OP_FLOAT_TO_INT32); PRINT_OP(OP_INT32_TO_INT64); PRINT_OP(OP_INT64_TO_INT32); PRINT_OP(OP_FLOAT_TO_INT64); PRINT_OP(OP_INT64_TO_FLOAT); PRINT_OP_INT32(OP_CALL); case OP_LINE: sPrintLine(); break; } } void btPrint(ByteCode* bt) { code = bt; readIndex = 0; line = 0; btPrintHeading(); while(readIndex < code->length) { btConsumeOperation(); } }