Start work on throw and catch

This commit is contained in:
2026-04-14 10:50:27 +10:00
parent 124245f492
commit ca85550c92
5 changed files with 90 additions and 5 deletions

View File

@@ -16,7 +16,10 @@
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, AND, OR, XOR, NEG, SHIFT, STOI, STOD, ITOC, CTOI, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, CALLMETHOD, STRUCT, ENDSTRUCT, INIT, GETFIELD, SETFIELD, USE, EXTERN, CREATELABEL, PAUSE, DROP, LICENSE, ERRORCMD
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, AND, OR, XOR, NEG,
SHIFT, STOI, STOD, ITOC, CTOI, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, CALLMETHOD, STRUCT, ENDSTRUCT, INIT,
GETFIELD, SETFIELD, USE, EXTERN, CREATELABEL, PAUSE, DROP, LICENSE, ERRORCMD, THROW, CATCH
} GroundInstType;
typedef enum GroundValueType {

View File

@@ -125,6 +125,12 @@ GroundLabel* findLabel(GroundLabel* head, const char *id) {
return item;
}
GroundCatch* findCatch(GroundCatch* head, const char *id) {
GroundCatch *item;
HASH_FIND_STR(head, id, item);
return item;
}
void deleteLabel(GroundLabel** head, GroundLabel *item) {
HASH_DEL(*head, item);
free(item);
@@ -165,6 +171,7 @@ void deleteVariable(GroundVariable** head, GroundVariable *item) {
GroundScope scope = {
.labels = NULL,
.variables = malloc(sizeof(GroundVariable*)),
.catches = malloc(sizeof(GroundCatch*)),
.isMainScope = false
};
if (scope.variables == NULL) {
@@ -517,6 +524,7 @@ GroundStruct parseStruct(GroundProgram* in, GroundScope* scope, size_t errorOffs
GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
GroundLabel* labels = NULL;
GroundVariable* variables = NULL;
GroundCatch* catches = NULL;
int instructionsToPause = -1;
GroundScope scope;
@@ -525,6 +533,7 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
} else {
scope.labels = &labels;
scope.variables = &variables;
scope.catches = &catches;
}
scope.isMainScope = isMainScopeGlobal;
isMainScopeGlobal = false;
@@ -1955,6 +1964,13 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
returnValue.data.errorVal.line = currentInstruction;
returnValue.data.errorVal.hasLine = true;
returnValue.data.errorVal.where = in;
GroundCatch* catch = findCatch(*scope->catches, returnValue.data.errorVal.type);
if (catch != NULL) {
// Jump to label where catch points to
currentInstruction = catch->label->lineNum;
}
if (scope->isMainScope) {
throwError(&returnValue.data.errorVal);
}
@@ -2418,6 +2434,57 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
break;
}
case THROW: {
if (in->args.length < 2) {
runtimeError(TOO_FEW_ARGS, "Expecting 2 args", in, currentInstruction);
}
if (in->args.length > 2) {
runtimeError(TOO_MANY_ARGS, "Expecting 2 args", in, currentInstruction);
}
if (in->args.args[0].type != VALUE || in->args.args[0].value.value.type != STRING) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a String value for arg 1", in, currentInstruction);
}
if (in->args.args[1].type != VALUE || in->args.args[1].value.value.type != STRING) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a String value for arg 2", in, currentInstruction);
}
return createErrorGroundValue(
createGroundError(
in->args.args[0].value.value.data.stringVal,
in->args.args[1].value.value.data.stringVal,
in,
(size_t*)&currentInstruction
)
);
}
case CATCH: {
if (in->args.length < 2) {
runtimeError(TOO_FEW_ARGS, "Expecting 2 args", in, currentInstruction);
}
if (in->args.length > 2) {
runtimeError(TOO_MANY_ARGS, "Expecting 2 args", in, currentInstruction);
}
if (in->args.args[0].type != VALUE || in->args.args[0].value.value.type != STRING) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a String value for arg 1", in, currentInstruction);
}
if (in->args.args[1].type != LINEREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a LineRef for arg 2", in, currentInstruction);
}
GroundLabel* label = findLabel(*scope->labels, in->args.args[1].value.refName);
if (label == NULL) {
runtimeError(UNKNOWN_LABEL, NULL, in, currentInstruction);
}
GroundCatch catch = {
.label = label
};
HASH_ADD_STR(*scope->catches, id, &catch);
break;
}
/*
* License for REPL
*/
@@ -2427,6 +2494,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
break;
}
default: {
runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction);
}

View File

@@ -204,6 +204,8 @@ static GroundInstType getInstructionType(const char* inst) {
if (strcmp(inst, "extern") == 0) return EXTERN;
if (strcmp(inst, "drop") == 0) return DROP;
if (strcmp(inst, "license") == 0) return LICENSE;
if (strcmp(inst, "throw") == 0) return THROW;
if (strcmp(inst, "catch") == 0) return CATCH;
if (strcmp(inst, "PAUSE") == 0) return PAUSE;
fprintf(stderr, "Error: Unknown instruction: %s\n", inst);

View File

@@ -794,10 +794,12 @@ GroundScope copyGroundScope(GroundScope* scope) {
GroundScope newScope = {
.labels = malloc(sizeof(GroundLabel*)),
.variables = malloc(sizeof(GroundVariable*)),
.catches = malloc(sizeof(GroundCatch*)),
.isMainScope = false
};
*newScope.variables = NULL;
*newScope.labels = NULL;
*newScope.catches = NULL;
if (scope == NULL) {
printf("oh no scope is null\n");

View File

@@ -29,7 +29,10 @@ void wasm_print(const char* str);
#endif
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, AND, OR, XOR, NEG, SHIFT, STOI, STOD, ITOC, CTOI, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, CALLMETHOD, STRUCT, ENDSTRUCT, INIT, GETFIELD, SETFIELD, USE, EXTERN, CREATELABEL, PAUSE, DROP, LICENSE, ERRORCMD
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, AND, OR, XOR, NEG,
SHIFT, STOI, STOD, ITOC, CTOI, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, CALLMETHOD, STRUCT, ENDSTRUCT, INIT,
GETFIELD, SETFIELD, USE, EXTERN, CREATELABEL, PAUSE, DROP, LICENSE, ERRORCMD, THROW, CATCH
} GroundInstType;
typedef enum GroundValueType {
@@ -110,9 +113,16 @@ typedef struct GroundVariable {
bool freed;
} GroundVariable;
typedef struct GroundCatch {
char id[MAX_ID_LEN];
GroundLabel* label;
UT_hash_handle hh;
} GroundCatch;
typedef struct GroundScope {
GroundLabel** labels;
GroundVariable** variables;
GroundCatch** catches;
bool isMainScope;
} GroundScope;