Start working on debugger
This commit is contained in:
@@ -129,7 +129,8 @@ endif
|
||||
|
||||
|
||||
cli_sources = files(
|
||||
'src/cli/main.c'
|
||||
'src/cli/main.c',
|
||||
'src/cli/debugger.c'
|
||||
)
|
||||
|
||||
incdir = include_directories('include')
|
||||
|
||||
140
src/cli/debugger.c
Normal file
140
src/cli/debugger.c
Normal file
@@ -0,0 +1,140 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "../../include/ground.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void runDebugger(GroundBytecode* bytecode);
|
||||
|
||||
enum ArgsAction {
|
||||
ARGS_HELP, ARGS_EXECUTE, ARGS_DEBUG, ARGS_ASSEMBLE, ARGS_DISASSEMBLE
|
||||
};
|
||||
@@ -73,7 +75,20 @@ int main(int argc, char** argv) {
|
||||
break;
|
||||
}
|
||||
case ARGS_DEBUG: {
|
||||
fprintf(stderr, "Not yet implemented");
|
||||
if (args.inputFile == NULL) {
|
||||
fprintf(stderr, "Please specify a bytecode file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
GroundBytecode bc = Ground.Bytecode.load(args.inputFile);
|
||||
if (Ground.Flags.error) {
|
||||
fprintf(stderr, "Failed to load bytecode, printing errors...\n");
|
||||
Ground.Log.printErrors();
|
||||
return 1;
|
||||
}
|
||||
|
||||
runDebugger(&bc);
|
||||
|
||||
break;
|
||||
}
|
||||
case ARGS_ASSEMBLE: {
|
||||
|
||||
Reference in New Issue
Block a user