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 { 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; } GroundInstType;
typedef enum GroundValueType { typedef enum GroundValueType {

View File

@@ -125,6 +125,12 @@ GroundLabel* findLabel(GroundLabel* head, const char *id) {
return item; 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) { void deleteLabel(GroundLabel** head, GroundLabel *item) {
HASH_DEL(*head, item); HASH_DEL(*head, item);
free(item); free(item);
@@ -165,6 +171,7 @@ void deleteVariable(GroundVariable** head, GroundVariable *item) {
GroundScope scope = { GroundScope scope = {
.labels = NULL, .labels = NULL,
.variables = malloc(sizeof(GroundVariable*)), .variables = malloc(sizeof(GroundVariable*)),
.catches = malloc(sizeof(GroundCatch*)),
.isMainScope = false .isMainScope = false
}; };
if (scope.variables == NULL) { if (scope.variables == NULL) {
@@ -517,6 +524,7 @@ GroundStruct parseStruct(GroundProgram* in, GroundScope* scope, size_t errorOffs
GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) { GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
GroundLabel* labels = NULL; GroundLabel* labels = NULL;
GroundVariable* variables = NULL; GroundVariable* variables = NULL;
GroundCatch* catches = NULL;
int instructionsToPause = -1; int instructionsToPause = -1;
GroundScope scope; GroundScope scope;
@@ -525,6 +533,7 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
} else { } else {
scope.labels = &labels; scope.labels = &labels;
scope.variables = &variables; scope.variables = &variables;
scope.catches = &catches;
} }
scope.isMainScope = isMainScopeGlobal; scope.isMainScope = isMainScopeGlobal;
isMainScopeGlobal = false; isMainScopeGlobal = false;
@@ -1955,6 +1964,13 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
returnValue.data.errorVal.line = currentInstruction; returnValue.data.errorVal.line = currentInstruction;
returnValue.data.errorVal.hasLine = true; returnValue.data.errorVal.hasLine = true;
returnValue.data.errorVal.where = in; 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) { if (scope->isMainScope) {
throwError(&returnValue.data.errorVal); throwError(&returnValue.data.errorVal);
} }
@@ -2418,6 +2434,57 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
break; 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 * License for REPL
*/ */
@@ -2427,6 +2494,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
break; break;
} }
default: { default: {
runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction); 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, "extern") == 0) return EXTERN;
if (strcmp(inst, "drop") == 0) return DROP; if (strcmp(inst, "drop") == 0) return DROP;
if (strcmp(inst, "license") == 0) return LICENSE; 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; if (strcmp(inst, "PAUSE") == 0) return PAUSE;
fprintf(stderr, "Error: Unknown instruction: %s\n", inst); fprintf(stderr, "Error: Unknown instruction: %s\n", inst);

View File

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

View File

@@ -29,7 +29,10 @@ void wasm_print(const char* str);
#endif #endif
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, 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; } GroundInstType;
typedef enum GroundValueType { typedef enum GroundValueType {
@@ -110,9 +113,16 @@ typedef struct GroundVariable {
bool freed; bool freed;
} GroundVariable; } GroundVariable;
typedef struct GroundCatch {
char id[MAX_ID_LEN];
GroundLabel* label;
UT_hash_handle hh;
} GroundCatch;
typedef struct GroundScope { typedef struct GroundScope {
GroundLabel** labels; GroundLabel** labels;
GroundVariable** variables; GroundVariable** variables;
GroundCatch** catches;
bool isMainScope; bool isMainScope;
} GroundScope; } GroundScope;