Better library stuff #7
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
51
src/types.c
51
src/types.c
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
22
src/types.h
22
src/types.h
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user