This commit is contained in:
2025-12-08 11:08:08 +11:00
parent 6e733910ec
commit bd1a47d118
7 changed files with 165 additions and 3 deletions

View File

@@ -149,9 +149,63 @@ GroundValueType stringToValueType(char* in) {
if (strcmp(in, "list") == 0) {
return LIST;
}
if (strcmp(in, "function") == 0) {
return FUNCTION;
}
return CUSTOM;
}
GroundDebugInstruction parseDebugInstruction(char* in) {
GroundDebugInstruction gdi;
size_t insize = strlen(in);
size_t spacepos = -1;
for (size_t i = 0; i < insize; i++) {
if (in[i] == ' ') {
spacepos = i;
break;
}
}
if (spacepos == -1) {
spacepos = insize;
}
char* instruction = malloc(spacepos + 1);
if (!instruction) {
gdi.type = UNKNOWN;
gdi.arg = NULL;
return gdi;
}
strncpy(instruction, in, spacepos);
instruction[spacepos] = '\0';
if (strcmp(instruction, "dump") == 0) {
gdi.type = DUMP;
} else if (strcmp(instruction, "inspect") == 0) {
gdi.type = INSPECT;
} else if (strcmp(instruction, "eval") == 0) {
gdi.type = EVAL;
} else if (strcmp(instruction, "continue") == 0) {
gdi.type = CONTINUE;
} else if (strcmp(instruction, "exit") == 0) {
gdi.type = EXIT;
} else if (strcmp(instruction, "help") == 0) {
gdi.type = HELP;
} else {
gdi.type = UNKNOWN;
}
size_t arglen = insize - spacepos;
gdi.arg = malloc(arglen + 1);
if (gdi.arg) {
strcpy(gdi.arg, in + spacepos + 1);
}
free(instruction);
return gdi;
}
GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
GroundLabel* labels = NULL;
GroundVariable* variables = NULL;
@@ -223,6 +277,92 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
}
}
}
if (in->instructions[i].type == PAUSE) {
printf("Paused execution\n");
printf("Previous instruction: ");
if (i > 0) {
printGroundInstruction(&in->instructions[i - 1]);
}
while (true) {
printf("\nprompt> ");
char buffer[256];
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
buffer[strcspn(buffer, "\n")] = '\0';
} else {
runtimeError(FIXME, "Failed to read input from console with fgets", NULL, -1);
}
GroundDebugInstruction gdi = parseDebugInstruction(buffer);
bool shouldBreak = false;
switch (gdi.type) {
case CONTINUE: {
shouldBreak = true;
break;
}
case EXIT: {
exit(0);
break;
}
case DUMP: {
if (scope.variables == NULL) {
printf("Can't access variables");
break;
}
if (*scope.variables == NULL) {
printf("Can't access variables");
break;
}
GroundVariable* entry;
GroundVariable* tmp;
GroundVariable* head = *scope.variables;
HASH_ITER(hh, head, entry, tmp) {
if (entry != NULL) {
printf("%s: ", entry->id);
printGroundValue(&entry->value);
printf("\n");
}
}
break;
}
case INSPECT: {
printf("%s: ", gdi.arg);
GroundVariable* var = findVariable(*scope.variables, gdi.arg);
if (var == NULL) {
printf("(nothing)");
} else {
printGroundValue(&var->value);
}
break;
}
case EVAL: {
GroundProgram program = parseFile(gdi.arg);
interpretGroundProgram(&program, &scope);
freeGroundProgram(&program);
break;
}
case HELP: {
printf("Ground Debugger Help\n");
printf("Didn't mean to end up here? Type \"continue\" to escape this prompt.\n");
printf("Commands:\n");
printf(" continue: Continue execution of the program\n");
printf(" exit: Stop execution early\n");
printf(" dump: Shows all variables and their contents\n");
printf(" inspect (variable): Shows the contents of a variable\n");
printf(" eval (code): Runs Ground code in the current scope\n");
printf(" help: Shows this help message");
}
case UNKNOWN: {
printf("Unknown instruction (type \"help\" for help)");
break;
}
}
if (shouldBreak) {
break;
}
}
continue;
}
int ci = currentInstruction;
GroundValue gv = interpretGroundInstruction(in->instructions[i], &scope);
if (gv.type != NONE) {

View File

@@ -10,6 +10,10 @@ typedef enum GroundRuntimeError {
ARG_TYPE_MISMATCH, TOO_FEW_ARGS, TOO_MANY_ARGS, UNKNOWN_LABEL, UNKNOWN_VARIABLE, LIST_ERROR, STRING_ERROR, MATH_ERROR, RETURN_TYPE_MISMATCH, FIXME
} GroundRuntimeError;
typedef enum GroundDebugInstructionType {
DUMP, INSPECT, EVAL, CONTINUE, EXIT, HELP, UNKNOWN
} GroundDebugInstructionType;
typedef struct GroundLabel {
char id[MAX_ID_LEN];
int lineNum;
@@ -27,6 +31,11 @@ typedef struct GroundScope {
GroundVariable** variables;
} GroundScope;
typedef struct GroundDebugInstruction {
GroundDebugInstructionType type;
char* arg;
} GroundDebugInstruction;
GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope);
GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scope);

View File

@@ -169,6 +169,7 @@ static GroundInstType getInstructionType(const char* inst) {
if (strcmp(inst, "init") == 0) return INIT;
if (strcmp(inst, "use") == 0) return USE;
if (strcmp(inst, "extern") == 0) return EXTERN;
if (strcmp(inst, "PAUSE") == 0) return PAUSE;
fprintf(stderr, "Error: Unknown instruction: %s\n", inst);
exit(EXIT_FAILURE);

View File

@@ -126,6 +126,10 @@ void printGroundValue(GroundValue* gv) {
printf("]");
break;
}
case FUNCTION: {
printf("<function>");
break;
}
default: {
printf("FIXME");
break;

View File

@@ -8,7 +8,7 @@
#include <string.h>
typedef enum GroundInstType {
IF, JUMP, END, INPUT, PRINT, PRINTLN, SET, GETTYPE, EXISTS, SETLIST, SETLISTAT, GETLISTAT, GETLISTSIZE, LISTAPPEND, GETSTRSIZE, GETSTRCHARAT, ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUAL, INEQUAL, NOT, GREATER, LESSER, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, USE, EXTERN, CREATELABEL
IF, JUMP, END, INPUT, PRINT, PRINTLN, SET, GETTYPE, EXISTS, SETLIST, SETLISTAT, GETLISTAT, GETLISTSIZE, LISTAPPEND, GETSTRSIZE, GETSTRCHARAT, ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUAL, INEQUAL, NOT, GREATER, LESSER, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, USE, EXTERN, CREATELABEL, PAUSE
} GroundInstType;
typedef enum GroundValueType {

View File

@@ -1,5 +1,5 @@
fun !dingus -string -int &x
return "dinglefart"
fun !dingus -string
return "dingus"
endfun
call !dingus &e

8
tests/pause.grnd Normal file
View File

@@ -0,0 +1,8 @@
fun !dingle -int
endfun
set &x 5
set &y "dingle"
PAUSE
println "continuing"