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) { if (strcmp(in, "list") == 0) {
return LIST; return LIST;
} }
if (strcmp(in, "function") == 0) {
return FUNCTION;
}
return CUSTOM; 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) { GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
GroundLabel* labels = NULL; GroundLabel* labels = NULL;
GroundVariable* variables = 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; int ci = currentInstruction;
GroundValue gv = interpretGroundInstruction(in->instructions[i], &scope); GroundValue gv = interpretGroundInstruction(in->instructions[i], &scope);
if (gv.type != NONE) { 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 ARG_TYPE_MISMATCH, TOO_FEW_ARGS, TOO_MANY_ARGS, UNKNOWN_LABEL, UNKNOWN_VARIABLE, LIST_ERROR, STRING_ERROR, MATH_ERROR, RETURN_TYPE_MISMATCH, FIXME
} GroundRuntimeError; } GroundRuntimeError;
typedef enum GroundDebugInstructionType {
DUMP, INSPECT, EVAL, CONTINUE, EXIT, HELP, UNKNOWN
} GroundDebugInstructionType;
typedef struct GroundLabel { typedef struct GroundLabel {
char id[MAX_ID_LEN]; char id[MAX_ID_LEN];
int lineNum; int lineNum;
@@ -27,6 +31,11 @@ typedef struct GroundScope {
GroundVariable** variables; GroundVariable** variables;
} GroundScope; } GroundScope;
typedef struct GroundDebugInstruction {
GroundDebugInstructionType type;
char* arg;
} GroundDebugInstruction;
GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope); GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope);
GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scope); 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, "init") == 0) return INIT;
if (strcmp(inst, "use") == 0) return USE; if (strcmp(inst, "use") == 0) return USE;
if (strcmp(inst, "extern") == 0) return EXTERN; if (strcmp(inst, "extern") == 0) return EXTERN;
if (strcmp(inst, "PAUSE") == 0) return PAUSE;
fprintf(stderr, "Error: Unknown instruction: %s\n", inst); fprintf(stderr, "Error: Unknown instruction: %s\n", inst);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

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

View File

@@ -8,7 +8,7 @@
#include <string.h> #include <string.h>
typedef enum GroundInstType { 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; } GroundInstType;
typedef enum GroundValueType { typedef enum GroundValueType {

View File

@@ -1,5 +1,5 @@
fun !dingus -string -int &x fun !dingus -string
return "dinglefart" return "dingus"
endfun endfun
call !dingus &e 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"