141 lines
3.8 KiB
C
141 lines
3.8 KiB
C
#include "../../include/ground.h"
|
|
#include "../linenoise/linenoise.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
typedef struct DebugCommand {
|
|
char* command;
|
|
struct {
|
|
char* at[32];
|
|
GroundSize count;
|
|
} args;
|
|
} DebugCommand;
|
|
|
|
static inline DebugCommand parseCommand(char* input) {
|
|
DebugCommand debugCommand;
|
|
// split by spaces
|
|
const char* delim = " ";
|
|
debugCommand.command = strtok(input, delim);
|
|
for (GroundSize i = 0; i < 32; i++) {
|
|
char* buf = strtok(NULL, delim);
|
|
if (buf == NULL) {
|
|
debugCommand.args.count = i;
|
|
break;
|
|
}
|
|
debugCommand.args.at[i] = buf;
|
|
}
|
|
|
|
return debugCommand;
|
|
}
|
|
|
|
typedef struct Debugger {
|
|
|
|
GroundSize currentInst;
|
|
|
|
} Debugger;
|
|
|
|
enum DebuggerStatus {
|
|
DBG_DONE, DBG_CONTINUE, DBG_WAIT, DBG_STEP
|
|
};
|
|
|
|
static inline enum DebuggerStatus runCommand(char* input, GroundBytecode* bytecode, Debugger* debugger) {
|
|
DebugCommand cmd = parseCommand(input);
|
|
if (strcmp(cmd.command, "help") == 0) {
|
|
printf(
|
|
"Commands: \n" \
|
|
" help - Show this help message\n" \
|
|
" continue - Run the program until next breakpoint, error, or otherwise termination\n" \
|
|
" step - Run one instruction\n" \
|
|
" break [idx] - Sets a breakpoint on the specified index\n" \
|
|
" exit - Stop debugging and exit\n\n" \
|
|
|
|
" dump - Dump current state of VM\n" \
|
|
" view [slot] - Prints the variable in the current slot\n" \
|
|
" set [slot] [value] - Sets the current slot to the specified value\n" \
|
|
" copy [slot] [slot] - Copies a value from the second slot to the first\n" \
|
|
);
|
|
return DBG_CONTINUE;
|
|
}
|
|
if (strcmp(cmd.command, "continue") == 0) {
|
|
return DBG_CONTINUE;
|
|
}
|
|
if (strcmp(cmd.command, "step") == 0) {
|
|
return DBG_STEP;
|
|
}
|
|
if (strcmp(cmd.command, "break") == 0) {
|
|
return DBG_WAIT;
|
|
}
|
|
if (strcmp(cmd.command, "exit") == 0) {
|
|
return DBG_DONE;
|
|
}
|
|
|
|
if (strcmp(cmd.command, "dump") == 0) {
|
|
printf("%s", Ground.Stringify.Bytecode(bytecode));
|
|
return DBG_WAIT;
|
|
}
|
|
if (strcmp(cmd.command, "view") == 0) {
|
|
return DBG_WAIT;
|
|
}
|
|
if (strcmp(cmd.command, "set") == 0) {
|
|
return DBG_WAIT;
|
|
}
|
|
if (strcmp(cmd.command, "copy") == 0) {
|
|
return DBG_WAIT;
|
|
}
|
|
|
|
fprintf(stderr, "Unknown command %s\n", cmd.command);
|
|
return DBG_WAIT;
|
|
}
|
|
|
|
static inline void runInstruction(GroundBytecodeProgram* program, GroundBytecodeHeap* heap) {
|
|
GroundSize i = 0;
|
|
while (i < program->len) {
|
|
struct GroundExecutionResult status = Ground.Bytecode.Instruction.execute(&program->at[i], heap);
|
|
if (Ground.Flags.error) {
|
|
fprintf(stderr, "Errors while debugging: \n");
|
|
Ground.Log.printErrors();
|
|
}
|
|
|
|
switch (status.type) {
|
|
|
|
case _GER_CONTINUE: i++; break;
|
|
case _GER_RETURN: return;
|
|
case _GER_JUMP: i = status.as.line; break;
|
|
case _GER_END: exit(status.as.end);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void runDebugger(GroundBytecode* bytecode) {
|
|
printf("Ground Debugger\n");
|
|
printf("Type 'help' for a list of commands\n");
|
|
printf("Type 'start' to begin debugging\n");
|
|
printf("Type 'exit' to exit\n");
|
|
|
|
Debugger debugger;
|
|
|
|
for (;;) {
|
|
char* input = linenoise("> ");
|
|
if (input == NULL) {
|
|
continue;
|
|
}
|
|
switch (runCommand(input, bytecode, &debugger)) {
|
|
case DBG_DONE: {
|
|
return;
|
|
}
|
|
case DBG_CONTINUE: {
|
|
break;
|
|
}
|
|
case DBG_WAIT: {
|
|
break;
|
|
}
|
|
case DBG_STEP: {
|
|
break;
|
|
}
|
|
}
|
|
free(input);
|
|
}
|
|
}
|