Better library stuff #7

Merged
max merged 3 commits from unstable into master 2026-01-19 20:01:56 +11:00
4 changed files with 106 additions and 1 deletions
Showing only changes of commit 72162a7410 - Show all commits

View File

@@ -11,6 +11,8 @@
int currentInstruction = 0; int currentInstruction = 0;
bool isMainScopeGlobal = true;
[[noreturn]] void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where, int whereLine) { [[noreturn]] void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where, int whereLine) {
printf("Ground runtime error:\n ErrorType: "); printf("Ground runtime error:\n ErrorType: ");
switch (error) { switch (error) {
@@ -78,6 +80,22 @@ int currentInstruction = 0;
exit(1); exit(1);
} }
[[noreturn]] void throwError(GroundError* error) {
printf("Uncaught Ground runtime error:\n ErrorType: %s\n", error->type);
if (error->what != NULL) {
printf(" ErrorContext: %s\n", error->what);
}
if (error->where != NULL) {
printf(" ErrorInstruction: ");
printGroundInstruction(error->where);
printf("\n");
}
if (error->line > -1) {
printf(" ErrorLine: %zu\n", error->line + 1);
}
exit(1);
}
GroundLabel* findLabel(GroundLabel* head, const char *id) { GroundLabel* findLabel(GroundLabel* head, const char *id) {
GroundLabel *item; GroundLabel *item;
HASH_FIND_STR(head, id, item); HASH_FIND_STR(head, id, item);
@@ -438,6 +456,8 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
scope.labels = &labels; scope.labels = &labels;
scope.variables = &variables; scope.variables = &variables;
} }
scope.isMainScope = isMainScopeGlobal;
isMainScopeGlobal = false;
// Preprocess all labels, structs and functions // Preprocess all labels, structs and functions
for (size_t i = 0; i < in->size; i++) { for (size_t i = 0; i < in->size; i++) {
if (in->instructions[i].type == CREATELABEL) { if (in->instructions[i].type == CREATELABEL) {
@@ -872,6 +892,10 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("none")); addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("none"));
break; break;
} }
case ERROR: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("error"));
break;
}
} }
break; break;
@@ -1737,6 +1761,12 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
if (function->nativeFn) { if (function->nativeFn) {
GroundValue returnValue = function->nativeFn(scope, argsList); GroundValue returnValue = function->nativeFn(scope, argsList);
if (returnValue.type == ERROR) {
if (scope->isMainScope) {
throwError(&returnValue.data.errorVal);
}
return returnValue;
}
if (returnValue.type != function->returnType) { if (returnValue.type != function->returnType) {
runtimeError(RETURN_TYPE_MISMATCH, "Unexpected return value type from native function", in, currentInstruction); runtimeError(RETURN_TYPE_MISMATCH, "Unexpected return value type from native function", in, currentInstruction);
} }
@@ -1756,6 +1786,9 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
size_t currentCurrentInstruction = currentInstruction; size_t currentCurrentInstruction = currentInstruction;
currentInstruction = function->startLine; currentInstruction = function->startLine;
GroundValue returnValue = interpretGroundProgram(&function->program, &newScope); GroundValue returnValue = interpretGroundProgram(&function->program, &newScope);
if (returnValue.type == ERROR) {
return returnValue;
}
if (returnValue.type != function->returnType) { if (returnValue.type != function->returnType) {
runtimeError(RETURN_TYPE_MISMATCH, "Unexpected return value type from function", in, currentInstruction); runtimeError(RETURN_TYPE_MISMATCH, "Unexpected return value type from function", in, currentInstruction);
} }

View File

@@ -29,6 +29,7 @@ typedef struct GroundVariable {
typedef struct GroundScope { typedef struct GroundScope {
GroundLabel** labels; GroundLabel** labels;
GroundVariable** variables; GroundVariable** variables;
bool isMainScope;
} GroundScope; } GroundScope;
typedef struct GroundDebugInstruction { typedef struct GroundDebugInstruction {

View File

@@ -51,6 +51,13 @@ GroundValue createFunctionGroundValue(GroundFunction* in) {
return gv; return gv;
} }
GroundValue createErrorGroundValue(GroundError in) {
GroundValue gv;
gv.data.errorVal = in;
gv.type = ERROR;
return gv;
}
GroundValue createNoneGroundValue() { GroundValue createNoneGroundValue() {
GroundValue gv; GroundValue gv;
gv.type = NONE; gv.type = NONE;
@@ -168,6 +175,18 @@ void freeGroundValue(GroundValue* gv) {
freeGroundStruct(gstruct); freeGroundStruct(gstruct);
free(gstruct); free(gstruct);
} }
if (gv->type == ERROR) {
GroundError* error = &gv->data.errorVal;
if (error->type != NULL) {
free(error->type);
}
if (error->what != NULL) {
free(error->what);
}
if (error->where != NULL) {
freeGroundInstruction(error->where);
}
}
} }
GroundArg createValueGroundArg(GroundValue value) { GroundArg createValueGroundArg(GroundValue value) {
@@ -529,3 +548,35 @@ void freeGroundObject(GroundObject* object) {
} }
object->fields = NULL; object->fields = NULL;
} }
GroundError createGroundError(char* what, char* type, GroundInstruction* where, size_t* line) {
GroundError ge;
if (what != NULL) {
ge.what = malloc(strlen(what) + 1);
strcpy(ge.what, what);
} else {
ge.what = NULL;
}
if (type != NULL) {
ge.type = malloc(strlen(type) + 1);
strcpy(ge.type, type);
} else {
ge.type = "GenericError";
}
if (where != NULL) {
ge.where = malloc(sizeof(GroundInstruction));
*ge.where = copyGroundInstruction(where);
} else {
ge.where = NULL;
}
if (line != NULL) {
ge.line = *line;
} else {
ge.line = -1;
}
return ge;
}

View File

@@ -13,7 +13,7 @@ typedef enum GroundInstType {
} GroundInstType; } GroundInstType;
typedef enum GroundValueType { typedef enum GroundValueType {
INT, DOUBLE, STRING, CHAR, BOOL, LIST, FUNCTION, STRUCTVAL, CUSTOM, NONE INT, DOUBLE, STRING, CHAR, BOOL, LIST, FUNCTION, STRUCTVAL, CUSTOM, ERROR, NONE
} GroundValueType; } GroundValueType;
typedef enum GroundArgType { typedef enum GroundArgType {
@@ -29,6 +29,7 @@ struct GroundFunction;
struct GroundScope; struct GroundScope;
struct GroundStruct; struct GroundStruct;
struct GroundObject; struct GroundObject;
struct GroundInstruction;
struct List; struct List;
@@ -42,6 +43,16 @@ typedef struct List {
struct GroundValue* values; struct GroundValue* values;
} List; } List;
/*
* Stores data associated with an error thrown during Ground execution.
*/
typedef struct GroundError {
char* what;
char* type;
struct GroundInstruction* where;
size_t line;
} GroundError;
/* /*
* Stores literal values created in a Ground program. * Stores literal values created in a Ground program.
* Associated functions: * Associated functions:
@@ -57,6 +68,7 @@ typedef struct GroundValue {
char charVal; char charVal;
bool boolVal; bool boolVal;
List listVal; List listVal;
GroundError errorVal;
struct GroundFunction* fnVal; struct GroundFunction* fnVal;
struct GroundStruct* structVal; struct GroundStruct* structVal;
struct GroundObject* customVal; struct GroundObject* customVal;
@@ -187,6 +199,9 @@ GroundValue createListGroundValue(List in);
// Creates a GroundValue conatining (in), with type FUNCTION. // Creates a GroundValue conatining (in), with type FUNCTION.
GroundValue createFunctionGroundValue(GroundFunction* in); GroundValue createFunctionGroundValue(GroundFunction* in);
// Creates a GroundValue containing (in), with type ERROR.
GroundValue createErrorGroundValue(GroundError in);
// Creates a Groundvalue with type NONE. // Creates a Groundvalue with type NONE.
GroundValue createNoneGroundValue(); GroundValue createNoneGroundValue();
@@ -257,4 +272,9 @@ GroundObjectField* findField(GroundObject head, const char *id);
// Frees a GroundObject // Frees a GroundObject
void freeGroundObject(GroundObject* object); void freeGroundObject(GroundObject* object);
// Creates a GroundError.
GroundError createGroundError(char* what, char* type, GroundInstruction* where, size_t* line);
#endif #endif