Struct definitions #6

Merged
max merged 8 commits from unstable into master 2026-01-18 20:35:09 +11:00
4 changed files with 68 additions and 23 deletions
Showing only changes of commit 96d7d9470a - Show all commits

View File

@@ -11,7 +11,7 @@
int currentInstruction = 0; int currentInstruction = 0;
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) {
case ARG_TYPE_MISMATCH: { case ARG_TYPE_MISMATCH: {
@@ -46,6 +46,18 @@ void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where
printf("MathError"); printf("MathError");
break; break;
} }
case RETURN_TYPE_MISMATCH: {
printf("ReturnTypeMismatch");
break;
}
case PREMATURE_EOF: {
printf("PrematureEof");
break;
}
case INVALID_INSTRUCTION: {
printf("InvalidInstruction");
break;
}
default: default:
case FIXME: { case FIXME: {
printf("FIXME (please report issue to https://chsp.au/ground/cground)"); printf("FIXME (please report issue to https://chsp.au/ground/cground)");
@@ -173,7 +185,7 @@ GroundDebugInstruction parseDebugInstruction(char* in) {
} }
} }
if (spacepos == -1) { if (spacepos == (size_t) -1) {
spacepos = insize; spacepos = insize;
} }
@@ -234,8 +246,25 @@ void groundAddNativeFunction(GroundScope* scope, char* name, NativeGroundFunctio
addVariable(scope->variables, name, createFunctionGroundValue(gf)); addVariable(scope->variables, name, createFunctionGroundValue(gf));
} }
GroundStruct parseStruct(GroundProgram* in) { GroundStruct parseStruct(GroundProgram* in, size_t errorOffset) {
GroundStruct gstruct = createStruct(); GroundStruct gstruct = createStruct();
for (size_t i = 0; i < in->size; i++) {
switch (in->instructions[i].type) {
case SET: {
break;
}
case INIT: {
break;
}
case FUN: {
break;
}
default: {
runtimeError(INVALID_INSTRUCTION, "Unsupported instruction while inside struct", &in->instructions[i], errorOffset + i);
}
}
}
return gstruct; return gstruct;
} }
@@ -252,7 +281,7 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
scope.variables = &variables; scope.variables = &variables;
} }
// Preprocess all labels, structs and functions // Preprocess all labels, structs and functions
for (int 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) {
addLabel(scope.labels, in->instructions[i].args.args[0].value.refName, i); addLabel(scope.labels, in->instructions[i].args.args[0].value.refName, i);
} }
@@ -309,7 +338,8 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
i++; i++;
size_t counter = 1; size_t counter = 1;
GroundProgram gp; GroundProgram gp = createGroundProgram();
size_t errorOffset = i;
while (counter > 0) { while (counter > 0) {
if (i >= in->size) { if (i >= in->size) {
runtimeError(PREMATURE_EOF, "Reached end of scope before struct definition ended", &in->instructions[i - 1], i - 1); runtimeError(PREMATURE_EOF, "Reached end of scope before struct definition ended", &in->instructions[i - 1], i - 1);
@@ -321,12 +351,13 @@ GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope) {
counter--; counter--;
} }
addInstructionToProgram(&gp, in->instructions[i]); addInstructionToProgram(&gp, in->instructions[i]);
i++;
} }
GroundStruct gs = parseStruct(&gp); GroundStruct gs = parseStruct(&gp, errorOffset);
} }
} }
for (int i = 0; i < in->size; i++) { for (size_t i = 0; i < in->size; i++) {
if (in->instructions[i].type == FUN) { if (in->instructions[i].type == FUN) {
int count = 1; int count = 1;
while (count > 0) { while (count > 0) {
@@ -463,7 +494,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
GroundInstruction* in = &copied_inst; GroundInstruction* in = &copied_inst;
// Insert variables prefixed with $ // Insert variables prefixed with $
for (int i = 0; i < in->args.length; i++) { for (size_t i = 0; i < in->args.length; i++) {
if (in->args.args[i].type == VALREF) { if (in->args.args[i].type == VALREF) {
GroundVariable* variable = findVariable(*scope->variables, in->args.args[i].value.refName); GroundVariable* variable = findVariable(*scope->variables, in->args.args[i].value.refName);
if (variable) { if (variable) {
@@ -476,9 +507,11 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
} }
} }
switch (in->type) { switch (in->type) {
// We can safely ignore any CREATELABEL, FUN, and ENDFUN instructions, these have been preprocessed // We can safely ignore these instructions, as they have been preprocessed
case FUN: case FUN:
case ENDFUN: case ENDFUN:
case STRUCT:
case ENDSTRUCT:
case CREATELABEL: { case CREATELABEL: {
break; break;
} }
@@ -551,7 +584,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
if (in->args.length < 1) { if (in->args.length < 1) {
runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction); runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction);
} }
for (int i = 0; i < in->args.length; i++) { for (size_t i = 0; i < in->args.length; i++) {
if (i != 0) printf(" "); if (i != 0) printf(" ");
printGroundArg(&in->args.args[i]); printGroundArg(&in->args.args[i]);
} }
@@ -561,7 +594,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
if (in->args.length < 1) { if (in->args.length < 1) {
runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction); runtimeError(TOO_FEW_ARGS, "Expecting 1 or more args", in, currentInstruction);
} }
for (int i = 0; i < in->args.length; i++) { for (size_t i = 0; i < in->args.length; i++) {
if (i != 0) printf(" "); if (i != 0) printf(" ");
printGroundArg(&in->args.args[i]); printGroundArg(&in->args.args[i]);
} }
@@ -653,9 +686,15 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
} }
case FUNCTION: { case FUNCTION: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("function")); addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("function"));
break;
}
case STRUCTVAL: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("struct"));
break;
} }
case NONE: { case NONE: {
addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("none")); addVariable(scope->variables, in->args.args[1].value.refName, createStringGroundValue("none"));
break;
} }
} }
@@ -690,7 +729,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 1", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 1", in, currentInstruction);
} }
List newList = createList(); List newList = createList();
for (int i = 1; i < in->args.length; i++) { for (size_t i = 1; i < in->args.length; i++) {
if (in->args.args[i].type != VALUE) { if (in->args.args[i].type != VALUE) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for all args after arg 1", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for all args after arg 1", in, currentInstruction);
} }
@@ -1167,7 +1206,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 3", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 3", in, currentInstruction);
} }
char* str = in->args.args[0].value.value.data.stringVal; char* str = in->args.args[0].value.value.data.stringVal;
int64_t idx = in->args.args[1].value.value.data.intVal; size_t idx = in->args.args[1].value.value.data.intVal;
if (idx < strlen(str)) { if (idx < strlen(str)) {
addVariable(scope->variables, in->args.args[2].value.refName, createCharGroundValue(str[idx])); addVariable(scope->variables, in->args.args[2].value.refName, createCharGroundValue(str[idx]));
} else { } else {

View File

@@ -7,7 +7,7 @@
#include "include/uthash.h" #include "include/uthash.h"
typedef enum GroundRuntimeError { 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, PREMATURE_EOF, FIXME ARG_TYPE_MISMATCH, TOO_FEW_ARGS, TOO_MANY_ARGS, UNKNOWN_LABEL, UNKNOWN_VARIABLE, LIST_ERROR, STRING_ERROR, MATH_ERROR, RETURN_TYPE_MISMATCH, PREMATURE_EOF, INVALID_INSTRUCTION, FIXME
} GroundRuntimeError; } GroundRuntimeError;
typedef enum GroundDebugInstructionType { typedef enum GroundDebugInstructionType {
@@ -36,9 +36,11 @@ typedef struct GroundDebugInstruction {
char* arg; char* arg;
} GroundDebugInstruction; } GroundDebugInstruction;
GroundStruct parseStruct(GroundProgram* in); GroundStruct parseStruct(GroundProgram* in, size_t errorOffset);
GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope); GroundValue interpretGroundProgram(GroundProgram* in, GroundScope* inScope);
GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scope); GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scope);
#endif #endif

View File

@@ -74,7 +74,7 @@ GroundValue copyGroundValue(const GroundValue* gv) {
break; break;
case LIST: { case LIST: {
List newList = createList(); List newList = createList();
for (int i = 0; i < gv->data.listVal.size; i++) { for (size_t i = 0; i < gv->data.listVal.size; i++) {
// Recursive call to handle nested lists and other types // Recursive call to handle nested lists and other types
appendToList(&newList, copyGroundValue(&gv->data.listVal.values[i])); appendToList(&newList, copyGroundValue(&gv->data.listVal.values[i]));
} }
@@ -93,6 +93,10 @@ GroundValue copyGroundValue(const GroundValue* gv) {
// FIXME // FIXME
newGv.data.customVal = gv->data.customVal; newGv.data.customVal = gv->data.customVal;
break; break;
case NONE:
default: {
}
} }
return newGv; return newGv;
} }
@@ -125,7 +129,7 @@ void printGroundValue(GroundValue* gv) {
} }
case LIST: { case LIST: {
printf("["); printf("[");
for (int i = 0; i < gv->data.listVal.size; i++) { for (size_t i = 0; i < gv->data.listVal.size; i++) {
printGroundValue(&gv->data.listVal.values[i]); printGroundValue(&gv->data.listVal.values[i]);
if (i < gv->data.listVal.size - 1) { if (i < gv->data.listVal.size - 1) {
printf(", "); printf(", ");
@@ -152,7 +156,7 @@ void freeGroundValue(GroundValue* gv) {
} }
if (gv->type == LIST && gv->data.listVal.values != NULL) { if (gv->type == LIST && gv->data.listVal.values != NULL) {
List* list = &gv->data.listVal; List* list = &gv->data.listVal;
for (int i = 0; i < list->size; i++) { for (size_t i = 0; i < list->size; i++) {
freeGroundValue(&list->values[i]); freeGroundValue(&list->values[i]);
} }
free(list->values); free(list->values);
@@ -394,7 +398,7 @@ void printGroundInstruction(GroundInstruction* gi) {
break; break;
} }
if (gi->type != CREATELABEL) printf(" "); if (gi->type != CREATELABEL) printf(" ");
for (int i = 0; i < gi->args.length; i++) { for (size_t i = 0; i < gi->args.length; i++) {
if (gi->args.args[i].type == VALUE && gi->args.args[i].value.value.type == STRING) { if (gi->args.args[i].type == VALUE && gi->args.args[i].value.value.type == STRING) {
printf("\""); printf("\"");
printGroundArg(&gi->args.args[i]); printGroundArg(&gi->args.args[i]);
@@ -428,7 +432,7 @@ void appendToList(List* list, GroundValue value) {
list->values[list->size - 1] = value; list->values[list->size - 1] = value;
} }
ListAccess getListAt(List* list, int idx) { ListAccess getListAt(List* list, size_t idx) {
if (list == NULL) { if (list == NULL) {
printf("Expecting a List ptr, got a null pointer instead.\nThis is likely not an error with your Ground program.\nPlease report this issue to https://chsp.au/ground/cground\n"); printf("Expecting a List ptr, got a null pointer instead.\nThis is likely not an error with your Ground program.\nPlease report this issue to https://chsp.au/ground/cground\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@@ -446,7 +450,7 @@ ListAccess getListAt(List* list, int idx) {
} }
} }
ListAccessStatus setListAt(List* list, int idx, GroundValue value) { ListAccessStatus setListAt(List* list, size_t idx, GroundValue value) {
if (list == NULL) { if (list == NULL) {
printf("Expecting a List ptr, got a null pointer instead.\nThis is likely not an error with your Ground program.\nPlease report this issue to https://chsp.au/ground/cground\n"); printf("Expecting a List ptr, got a null pointer instead.\nThis is likely not an error with your Ground program.\nPlease report this issue to https://chsp.au/ground/cground\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@@ -234,10 +234,10 @@ void appendToList(List* list, GroundValue value);
// Gets item at index (idx) from list (list). If there is an error, it // Gets item at index (idx) from list (list). If there is an error, it
// will be indicated in the status field. // will be indicated in the status field.
ListAccess getListAt(List* list, int idx); ListAccess getListAt(List* list, size_t idx);
// Sets an item in list (list) at index (idx) to GroundValue (value). // Sets an item in list (list) at index (idx) to GroundValue (value).
ListAccessStatus setListAt(List* list, int idx, GroundValue value); ListAccessStatus setListAt(List* list, size_t idx, GroundValue value);
// Creates a Ground struct // Creates a Ground struct
GroundStruct createStruct(); GroundStruct createStruct();