debug dump are now directly prints to stdout

This commit is contained in:
Thakee Nathees 2022-04-07 21:32:20 +05:30
parent d3bcbfb779
commit c1d36c666c
6 changed files with 137 additions and 201 deletions

View File

@ -2316,12 +2316,8 @@ static int compileFunction(Compiler* compiler, FuncType fn_type) {
compilerExitBlock(compiler); // Parameter depth. compilerExitBlock(compiler); // Parameter depth.
} }
#if DEBUG_DUMP_COMPILED_CODE #if DUMP_BYTECODE
pkByteBuffer buff; dumpFunctionCode(compiler->parser.vm, compiler->func->ptr);
pkByteBufferInit(&buff);
dumpFunctionCode(compiler->vm, compiler->func->ptr, &buff);
printf("%s", buff.data);
pkByteBufferClear(&buff, compiler->vm);
#endif #endif
compilerPopFunc(compiler); compilerPopFunc(compiler);
@ -3065,12 +3061,8 @@ PkResult compile(PKVM* vm, Script* script, const char* source,
script->classes.count = types_count; script->classes.count = types_count;
} }
#if DEBUG_DUMP_COMPILED_CODE #if DUMP_BYTECODE
pkByteBuffer buff; dumpFunctionCode(compiler->parser.vm, script->body);
pkByteBufferInit(&buff);
dumpFunctionCode(compiler->vm, script->body, &buff);
printf("%s", buff.data);
pkByteBufferClear(&buff, vm);
#endif #endif
// Return the compilation result. // Return the compilation result.

View File

@ -885,13 +885,7 @@ DEF(stdLangDisas,
if (!validateCond(vm, !fn->is_native, if (!validateCond(vm, !fn->is_native,
"Cannot disassemble native functions.")) return; "Cannot disassemble native functions.")) return;
pkByteBuffer buff; dumpFunctionCode(vm, fn);
pkByteBufferInit(&buff);
dumpFunctionCode(vm, fn, &buff);
String* dump = newString(vm, (const char*)buff.data);
pkByteBufferClear(&buff, vm);
RET(VAR_OBJ(dump));
} }
#ifdef DEBUG #ifdef DEBUG

View File

@ -18,30 +18,49 @@ static const char* op_names[] = {
#undef OPCODE #undef OPCODE
}; };
// Instead of writing foo("a long string", strlen("a long string") or static void dumpValue(PKVM* vm, Var value) {
// foo("a long string may be changed", 28) using _STR_AND_LEN would be cleaner. if (!vm->config.write_fn) return;
// And the strlen(literal cstring) will always optimized.
#define STR_AND_LEN(str) str, (uint32_t)strlen(str)
void dumpValue(PKVM* vm, Var value, pkByteBuffer* buff) {
String* repr = toRepr(vm, value); String* repr = toRepr(vm, value);
vmPushTempRef(vm, &repr->_super); vm->config.write_fn(vm, repr->data);
pkByteBufferAddString(buff, vm, repr->data, repr->length); // String repr will be garbage collected - No need to clean.
vmPopTempRef(vm);
} }
void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) { void dumpFunctionCode(PKVM* vm, Function* func) {
#define INDENTATION " " if (!vm->config.write_fn) return;
#define ADD_CHAR(vm, buff, c) pkByteBufferWrite(buff, vm, c)
#define INT_WIDTH 5 #define _INDENTATION " "
#define ADD_INTEGER(vm, buff, value, width) \ #define _INT_WIDTH 5 // Width of the integer string to print.
#define PRINT(str) vm->config.write_fn(vm, str)
#define NEWLINE() PRINT("\n")
#define _PRINT_INT(value, width) \
do { \ do { \
char sbuff[STR_INT_BUFF_SIZE]; \ char sbuff[STR_INT_BUFF_SIZE]; \
int length; \ int length; \
if ((width) > 0) length = sprintf(sbuff, "%*d", (width), value); \ if ((width) > 0) length = sprintf(sbuff, "%*d", (width), value); \
else length = sprintf(sbuff, "%d", value); \ else length = sprintf(sbuff, "%d", value); \
pkByteBufferAddString(buff, vm, sbuff, (uint32_t)length); \ sbuff[length] = '\0'; \
PRINT(sbuff); \
} while(false)
#define PRINT_INT(value) _PRINT_INT(value, _INT_WIDTH)
#define READ_BYTE() (opcodes[i++])
#define READ_SHORT() (i += 2, opcodes[i - 2] << 8 | opcodes[i-1])
#define NO_ARGS() NEWLINE()
#define BYTE_ARG() \
do { \
PRINT_INT(READ_BYTE()); \
NEWLINE(); \
} while (false)
#define SHORT_ARG() \
do { \
PRINT_INT(READ_SHORT()); \
NEWLINE(); \
} while (false) } while (false)
uint32_t i = 0; uint32_t i = 0;
@ -50,28 +69,11 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
uint32_t line = 1, last_line = 0; uint32_t line = 1, last_line = 0;
// This will print: Instruction Dump of function 'fn' "path.pk"\n // This will print: Instruction Dump of function 'fn' "path.pk"\n
pkByteBufferAddString(buff, vm, PRINT("Instruction Dump of function ");
STR_AND_LEN("Instruction Dump of function '")); PRINT(func->name);
pkByteBufferAddString(buff, vm, STR_AND_LEN(func->name)); PRINT(" ");
pkByteBufferAddString(buff, vm, STR_AND_LEN("' \"")); PRINT(func->owner->path->data);
pkByteBufferAddString(buff, vm, STR_AND_LEN(func->owner->path->data)); NEWLINE();
pkByteBufferAddString(buff, vm, STR_AND_LEN("\"\n"));
#define READ_BYTE() (opcodes[i++])
#define READ_SHORT() (i += 2, opcodes[i - 2] << 8 | opcodes[i-1])
#define NO_ARGS() ADD_CHAR(vm, buff, '\n')
#define BYTE_ARG() \
do { \
ADD_INTEGER(vm, buff, READ_BYTE(), INT_WIDTH); \
ADD_CHAR(vm, buff, '\n'); \
} while (false)
#define SHORT_ARG() \
do { \
ADD_INTEGER(vm, buff, READ_SHORT(), INT_WIDTH); \
ADD_CHAR(vm, buff, '\n'); \
} while (false)
while (i < func->fn->opcodes.count) { while (i < func->fn->opcodes.count) {
ASSERT_INDEX(i, func->fn->opcodes.count); ASSERT_INDEX(i, func->fn->opcodes.count);
@ -80,25 +82,24 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
line = lines[i]; line = lines[i];
if (line != last_line) { if (line != last_line) {
last_line = line; last_line = line;
pkByteBufferAddString(buff, vm, STR_AND_LEN(INDENTATION)); PRINT(_INDENTATION);
ADD_INTEGER(vm, buff, line, INT_WIDTH - 1); _PRINT_INT(line, _INT_WIDTH - 1);
ADD_CHAR(vm, buff, ':'); PRINT(":");
} else { } else {
pkByteBufferAddString(buff, vm, STR_AND_LEN(INDENTATION " ")); PRINT(_INDENTATION " ");
} }
// Prints: INDENTATION "%4d %-16s" // Prints: INDENTATION "%4d %-16s"
PRINT(_INDENTATION);
pkByteBufferAddString(buff, vm, STR_AND_LEN(INDENTATION)); _PRINT_INT(i, _INT_WIDTH - 1);
ADD_INTEGER(vm, buff, i, INT_WIDTH - 1); PRINT(_INDENTATION);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" "));
const char* op_name = op_names[opcodes[i]]; const char* op_name = op_names[opcodes[i]];
uint32_t op_length = (uint32_t)strlen(op_name); uint32_t op_length = (uint32_t)strlen(op_name);
pkByteBufferAddString(buff, vm, op_name, op_length); PRINT(op_name);
for (uint32_t j = 0; j < 16 - op_length; j++) { // Padding. for (uint32_t j = 0; j < 16 - op_length; j++) { // Padding.
ADD_CHAR(vm, buff, ' '); PRINT(" ");
} }
Opcode op = (Opcode)func->fn->opcodes.data[i++]; Opcode op = (Opcode)func->fn->opcodes.data[i++];
@ -110,10 +111,10 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
Var value = func->owner->literals.data[index]; Var value = func->owner->literals.data[index];
// Prints: %5d [val]\n // Prints: %5d [val]\n
ADD_INTEGER(vm, buff, index, INT_WIDTH); PRINT_INT(index);
ADD_CHAR(vm, buff, ' '); PRINT(" ");
dumpValue(vm, value, buff); dumpValue(vm, value);
ADD_CHAR(vm, buff, '\n'); NEWLINE();
break; break;
} }
@ -135,10 +136,10 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
String* ty_name = func->owner->names.data[name_ind]; String* ty_name = func->owner->names.data[name_ind];
// Prints: %5d [Ty:%s]\n // Prints: %5d [Ty:%s]\n
ADD_INTEGER(vm, buff, ty_index, INT_WIDTH); PRINT_INT(ty_index);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" [Ty:")); PRINT(" [Ty:");
pkByteBufferAddString(buff, vm, ty_name->data, ty_name->length); PRINT(ty_name->data);
pkByteBufferAddString(buff, vm, STR_AND_LEN("]\n")); PRINT("]\n");
break; break;
} }
case OP_PUSH_MAP: NO_ARGS(); break; case OP_PUSH_MAP: NO_ARGS(); break;
@ -161,21 +162,20 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
int arg; int arg;
if (op == OP_PUSH_LOCAL_N) { if (op == OP_PUSH_LOCAL_N) {
arg = READ_BYTE(); arg = READ_BYTE();
ADD_INTEGER(vm, buff, arg, INT_WIDTH); PRINT_INT(arg);
} else { } else {
arg = (int)(op - OP_PUSH_LOCAL_0); arg = (int)(op - OP_PUSH_LOCAL_0);
for (int j = 0; j < INT_WIDTH; j++) ADD_CHAR(vm, buff, ' '); for (int j = 0; j < _INT_WIDTH; j++) PRINT(" ");
} }
if (arg < func->arity) {
// Prints: (arg:%d)\n // Prints: (arg:%d)\n
pkByteBufferAddString(buff, vm, STR_AND_LEN(" (param:")); if (arg < func->arity) {
ADD_INTEGER(vm, buff, arg, 1); PRINT(" (param:");
pkByteBufferAddString(buff, vm, STR_AND_LEN(")\n")); _PRINT_INT(arg, 1);
PRINT(")\n");
} else { } else {
ADD_CHAR(vm, buff, '\n'); NEWLINE();
} }
} break; } break;
@ -194,21 +194,20 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
int arg; int arg;
if (op == OP_STORE_LOCAL_N) { if (op == OP_STORE_LOCAL_N) {
arg = READ_BYTE(); arg = READ_BYTE();
ADD_INTEGER(vm, buff, arg, INT_WIDTH); PRINT_INT(arg);
} else { } else {
arg = (int)(op - OP_STORE_LOCAL_0); arg = (int)(op - OP_STORE_LOCAL_0);
for (int j = 0; j < INT_WIDTH; j++) ADD_CHAR(vm, buff, ' '); for (int j = 0; j < _INT_WIDTH; j++) PRINT(" ");
} }
if (arg < func->arity) { if (arg < func->arity) {
// Prints: (arg:%d)\n // Prints: (arg:%d)\n
pkByteBufferAddString(buff, vm, STR_AND_LEN(" (param:")); PRINT(" (param:");
ADD_INTEGER(vm, buff, arg, 1); _PRINT_INT(arg, 1);
pkByteBufferAddString(buff, vm, STR_AND_LEN(")\n")); PRINT(")\n");
} else { } else {
ADD_CHAR(vm, buff, '\n'); NEWLINE();
} }
} break; } break;
@ -219,12 +218,11 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
int index = READ_BYTE(); int index = READ_BYTE();
int name_index = func->owner->global_names.data[index]; int name_index = func->owner->global_names.data[index];
String* name = func->owner->names.data[name_index]; String* name = func->owner->names.data[name_index];
// Prints: %5d '%s'\n // Prints: %5d '%s'\n
ADD_INTEGER(vm, buff, index, INT_WIDTH); PRINT_INT(index);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" '")); PRINT(" '");
pkByteBufferAddString(buff, vm, name->data, name->length); PRINT(name->data);
pkByteBufferAddString(buff, vm, STR_AND_LEN("'\n")); PRINT("'\n");
break; break;
} }
@ -232,12 +230,11 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
{ {
int fn_index = READ_BYTE(); int fn_index = READ_BYTE();
const char* name = func->owner->functions.data[fn_index]->name; const char* name = func->owner->functions.data[fn_index]->name;
// Prints: %5d [Fn:%s]\n // Prints: %5d [Fn:%s]\n
ADD_INTEGER(vm, buff, fn_index, INT_WIDTH); PRINT_INT(fn_index);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" [Fn:")); PRINT(" [Fn:");
pkByteBufferAddString(buff, vm, STR_AND_LEN(name)); PRINT(name);
pkByteBufferAddString(buff, vm, STR_AND_LEN("]\n")); PRINT("]\n");
break; break;
} }
@ -248,12 +245,11 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
uint32_t name_ind = func->owner->classes.data[ty_index]->name; uint32_t name_ind = func->owner->classes.data[ty_index]->name;
ASSERT_INDEX(name_ind, func->owner->names.count); ASSERT_INDEX(name_ind, func->owner->names.count);
String* ty_name = func->owner->names.data[name_ind]; String* ty_name = func->owner->names.data[name_ind];
// Prints: %5d [Ty:%s]\n // Prints: %5d [Ty:%s]\n
ADD_INTEGER(vm, buff, ty_index, INT_WIDTH); PRINT_INT(ty_index);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" [Ty:")); PRINT(" [Ty:");
pkByteBufferAddString(buff, vm, ty_name->data, ty_name->length); PRINT(ty_name->data);
pkByteBufferAddString(buff, vm, STR_AND_LEN("]\n")); PRINT("]\n");
break; break;
} }
@ -262,12 +258,11 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
{ {
int index = READ_BYTE(); int index = READ_BYTE();
const char* name = getBuiltinFunctionName(vm, index); const char* name = getBuiltinFunctionName(vm, index);
// Prints: %5d [Fn:%s]\n // Prints: %5d [Fn:%s]\n
ADD_INTEGER(vm, buff, index, INT_WIDTH); PRINT_INT(index);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" [Fn:")); PRINT(" [Fn:");
pkByteBufferAddString(buff, vm, STR_AND_LEN(name)); PRINT(name);
pkByteBufferAddString(buff, vm, STR_AND_LEN("]\n")); PRINT("]\n");
break; break;
} }
@ -276,25 +271,24 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
{ {
int index = READ_SHORT(); int index = READ_SHORT();
String* name = func->owner->names.data[index]; String* name = func->owner->names.data[index];
// Prints: %5d '%s'\n // Prints: %5d '%s'\n
ADD_INTEGER(vm, buff, index, INT_WIDTH); PRINT_INT(index);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" '")); PRINT(" '");
pkByteBufferAddString(buff, vm, name->data, name->length); PRINT(name->data);
pkByteBufferAddString(buff, vm, STR_AND_LEN("'\n")); PRINT("'\n");
break; break;
} }
case OP_CALL: case OP_CALL:
// Prints: %5d (argc)\n // Prints: %5d (argc)\n
ADD_INTEGER(vm, buff, READ_BYTE(), INT_WIDTH); PRINT_INT(READ_BYTE());
pkByteBufferAddString(buff, vm, STR_AND_LEN(" (argc)\n")); PRINT(" (argc)\n");
break; break;
case OP_TAIL_CALL: case OP_TAIL_CALL:
// Prints: %5d (argc)\n // Prints: %5d (argc)\n
ADD_INTEGER(vm, buff, READ_BYTE(), INT_WIDTH); PRINT_INT(READ_BYTE());
pkByteBufferAddString(buff, vm, STR_AND_LEN(" (argc)\n")); PRINT(" (argc)\n");
break; break;
case OP_ITER_TEST: NO_ARGS(); break; case OP_ITER_TEST: NO_ARGS(); break;
@ -307,24 +301,22 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
case OP_AND: case OP_AND:
{ {
int offset = READ_SHORT(); int offset = READ_SHORT();
// Prints: %5d (ip:%d)\n // Prints: %5d (ip:%d)\n
ADD_INTEGER(vm, buff, offset, INT_WIDTH); PRINT_INT(offset);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" (ip:")); PRINT(" (ip:");
ADD_INTEGER(vm, buff, i + offset, 0); _PRINT_INT(i + offset, 0);
pkByteBufferAddString(buff, vm, STR_AND_LEN(")\n")); PRINT(")\n");
break; break;
} }
case OP_LOOP: case OP_LOOP:
{ {
int offset = READ_SHORT(); int offset = READ_SHORT();
// Prints: %5d (ip:%d)\n // Prints: %5d (ip:%d)\n
ADD_INTEGER(vm, buff, -offset, INT_WIDTH); PRINT_INT(-offset);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" (ip:")); PRINT(" (ip:");
ADD_INTEGER(vm, buff, i - offset, 0); _PRINT_INT(i - offset, 0);
pkByteBufferAddString(buff, vm, STR_AND_LEN(")\n")); PRINT(")\n");
break; break;
} }
@ -336,12 +328,11 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
{ {
int index = READ_SHORT(); int index = READ_SHORT();
String* name = func->owner->names.data[index]; String* name = func->owner->names.data[index];
// Prints: %5d '%s'\n // Prints: %5d '%s'\n
ADD_INTEGER(vm, buff, index, INT_WIDTH); PRINT_INT(index);
pkByteBufferAddString(buff, vm, STR_AND_LEN(" '")); PRINT(" '");
pkByteBufferAddString(buff, vm, name->data, name->length); PRINT(name->data);
pkByteBufferAddString(buff, vm, STR_AND_LEN("'\n")); PRINT("'\n");
} break; } break;
case OP_GET_SUBSCRIPT: case OP_GET_SUBSCRIPT:
@ -382,35 +373,19 @@ void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff) {
} }
} }
ADD_CHAR(vm, buff, '\0'); NEWLINE();
// Undefin everything defined for this function. // Undefin everything defined for this function.
#undef INDENTATION #undef PRINT
#undef ADD_CHAR #undef NEWLINE
#undef STR_AND_LEN #undef _INT_WIDTH
#undef _INDENTATION
#undef READ_BYTE #undef READ_BYTE
#undef READ_SHORT #undef READ_SHORT
#undef BYTE_ARG #undef BYTE_ARG
#undef SHORT_ARG #undef SHORT_ARG
} }
//void dumpValue(PKVM* vm, Var value) {
// pkByteBuffer buff;
// pkByteBufferInit(&buff);
// _dumpValueInternal(vm, value, &buff);
// pkByteBufferWrite(&buff, vm, '\0');
// printf("%s", (const char*)buff.data);
//}
//
//void dumpFunctionCode(PKVM* vm, Function* func) {
// pkByteBuffer buff;
// pkByteBufferInit(&buff);
// _dumpFunctionCodeInternal(vm, func, &buff);
// pkByteBufferWrite(&buff, vm, '\0');
// printf("%s", (const char*)buff.data);
//}
void dumpGlobalValues(PKVM* vm) { void dumpGlobalValues(PKVM* vm) {
Fiber* fiber = vm->fiber; Fiber* fiber = vm->fiber;
int frame_ind = fiber->frame_count - 1; int frame_ind = fiber->frame_count - 1;
@ -422,15 +397,7 @@ void dumpGlobalValues(PKVM* vm) {
String* name = scr->names.data[scr->global_names.data[i]]; String* name = scr->names.data[scr->global_names.data[i]];
Var value = scr->globals.data[i]; Var value = scr->globals.data[i];
printf("%10s = ", name->data); printf("%10s = ", name->data);
dumpValue(vm, value);
// Dump value. TODO: refactor.
pkByteBuffer buff;
pkByteBufferInit(&buff);
dumpValue(vm, value, &buff);
pkByteBufferWrite(&buff, vm, '\0');
printf("%s", (const char*)buff.data);
pkByteBufferClear(&buff, vm);
printf("\n"); printf("\n");
} }
} }
@ -447,15 +414,8 @@ void dumpStackFrame(PKVM* vm) {
printf(" "); printf(" ");
// Dump value. TODO: refactor. // Dump value. TODO: refactor.
pkByteBuffer buff; dumpValue(vm, *sp);
pkByteBufferInit(&buff);
dumpValue(vm, *sp, &buff);
pkByteBufferWrite(&buff, vm, '\0');
printf("%s", (const char*)buff.data);
pkByteBufferClear(&buff, vm);
printf("\n"); printf("\n");
} }
} }
#undef _STR_AND_LEN

View File

@ -10,18 +10,13 @@
#include "pk_internal.h" #include "pk_internal.h"
#include "pk_value.h" #include "pk_value.h"
// Dump the value of the [value] without a new line at the end to the buffer // Dump opcodes of the given function to the stdout.
// [buff]. Note that this will not write a null byte at of the buffer void dumpFunctionCode(PKVM* vm, Function* func);
// (unlike dumpFunctionCode).
void dumpValue(PKVM* vm, Var value, pkByteBuffer* buff);
// Dump opcodes of the given function to the buffer [buff]. // Dump the all the global values of the script to the stdout.
void dumpFunctionCode(PKVM* vm, Function* func, pkByteBuffer* buff);
// Dump the all the global values of the script.
void dumpGlobalValues(PKVM* vm); void dumpGlobalValues(PKVM* vm);
// Dump the current (top most) stack call frame. // Dump the current (top most) stack call frame to the stdout.
void dumpStackFrame(PKVM* vm); void dumpStackFrame(PKVM* vm);
#endif // PK_DEBUG_H #endif // PK_DEBUG_H

View File

@ -43,10 +43,10 @@
/*****************************************************************************/ /*****************************************************************************/
// Set this to dump compiled opcodes of each functions. // Set this to dump compiled opcodes of each functions.
#define DEBUG_DUMP_COMPILED_CODE 0 #define DUMP_BYTECODE 0
// Set this to dump stack frame before executing the next instruction. // Dump the stack values and the globals.
#define DEBUG_DUMP_CALL_STACK 0 #define DUMP_STACK 0
// Nan-Tagging could be disable for debugging/portability purposes. See "var.h" // Nan-Tagging could be disable for debugging/portability purposes. See "var.h"
// header for more information on Nan-tagging. // header for more information on Nan-tagging.

View File

@ -658,31 +658,26 @@ static PkResult runFiber(PKVM* vm, Fiber* fiber) {
#error "OPCODE" should not be deifined here. #error "OPCODE" should not be deifined here.
#endif #endif
#if DEBUG_DUMP_CALL_STACK
#define DEBUG_CALL_STACK() \
do { \
system("cls"); /* FIXME */ \
dumpGlobalValues(vm); \
dumpStackFrame(vm); \
} while (false)
#else
#define DEBUG_CALL_STACK() NO_OP
#endif
#define SWITCH() Opcode instruction; switch (instruction = (Opcode)READ_BYTE()) #define SWITCH() Opcode instruction; switch (instruction = (Opcode)READ_BYTE())
#define OPCODE(code) case OP_##code #define OPCODE(code) case OP_##code
#define DISPATCH() goto L_vm_main_loop #define DISPATCH() goto L_vm_main_loop
// Trigger a break point here, if we're trying to debug the call stack.
#if DEBUG_DUMP_CALL_STACK
DEBUG_BREAK();
#endif
// Load the fiber's top call frame to the vm's execution variables. // Load the fiber's top call frame to the vm's execution variables.
LOAD_FRAME(); LOAD_FRAME();
L_vm_main_loop: L_vm_main_loop:
DEBUG_CALL_STACK();
#if DUMP_STACK
system("cls"); // FIXME:
dumpGlobalValues(vm);
dumpStackFrame(vm);
DEBUG_BREAK();
#else
// This NO_OP is required since Labels can only be followed by statements
// and, declarations are not statements (here: Opcode instruction;)
NO_OP;
#endif
SWITCH() { SWITCH() {
OPCODE(PUSH_CONSTANT): OPCODE(PUSH_CONSTANT):