Compare commits

...

7 Commits

5 changed files with 90 additions and 4 deletions

View File

@@ -13,6 +13,23 @@ int currentInstruction = 0;
bool isMainScopeGlobal = true; bool isMainScopeGlobal = true;
[[noreturn]] void customError(GroundArg type, GroundArg what, GroundInstruction* where, int whereLine, int exitCode) {
printf("Ground runtime error:\n ErrorType: ");
printGroundArg(&type);
printf("\n ErrorContext: ");
printGroundArg(&what);
printf("\n");
if (where != NULL) {
printf(" ErrorInstruction: ");
printGroundInstruction(where);
printf("\n");
}
if (whereLine > -1) {
printf(" ErrorLine: %d\n", whereLine + 1);
}
exit(exitCode);
}
[[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) {
@@ -382,6 +399,7 @@ GroundStruct parseStruct(GroundProgram* in, GroundScope* scope, size_t errorOffs
gv.type = CUSTOM; gv.type = CUSTOM;
gv.data.customVal = malloc(sizeof(GroundObject)); gv.data.customVal = malloc(sizeof(GroundObject));
*gv.data.customVal = createObject(*gstruct); *gv.data.customVal = createObject(*gstruct);
gv.customType = gstruct;
break; break;
} }
case NONE: { case NONE: {
@@ -813,7 +831,19 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
} }
break; break;
} }
case ERRORCMD: {
if (in->args.length < 3) {
runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction);
} else if (in->args.length > 3) {
runtimeError(TOO_MANY_ARGS, "Expecting 3 args", in, currentInstruction);
}
if (in->args.args[2].value.value.type != INT ) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting an int for arg 2", in, currentInstruction);
}
customError(in->args.args[0], in->args.args[1], in, currentInstruction, in->args.args[2].value.value.data.intVal);
break;
}
/* /*
* VARIABLES AND LISTS * VARIABLES AND LISTS
* These instructions are for initializing variables and lists. * These instructions are for initializing variables and lists.
@@ -1753,7 +1783,8 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
if (in->args.args[i + 1].type != VALUE) { if (in->args.args[i + 1].type != VALUE) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value", in, currentInstruction);
} }
if (in->args.args[i + 1].value.value.type != function->args[i].type) { //if (in->args.args[i + 1].value.value.type != function->args[i].type) {
if (!checkFnTypes(&in->args.args[i + 1].value.value, &function->args[i])) {
runtimeError(ARG_TYPE_MISMATCH, "Mismatched function argument types", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Mismatched function argument types", in, currentInstruction);
} }
appendToList(&argsList, in->args.args[i + 1].value.value); appendToList(&argsList, in->args.args[i + 1].value.value);
@@ -1781,7 +1812,8 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
if (in->args.args[i + 1].type != VALUE) { if (in->args.args[i + 1].type != VALUE) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value", in, currentInstruction);
} }
if (in->args.args[i + 1].value.value.type != function->args[i].type) { //if (in->args.args[i + 1].value.value.type != function->args[i].type) {
if (!checkFnTypes(&in->args.args[i + 1].value.value, &function->args[i])) {
runtimeError(ARG_TYPE_MISMATCH, "Mismatched function argument types", in, currentInstruction); runtimeError(ARG_TYPE_MISMATCH, "Mismatched function argument types", in, currentInstruction);
} }
addVariable(newScope.variables, function->args[i].name, in->args.args[i + 1].value.value); addVariable(newScope.variables, function->args[i].name, in->args.args[i + 1].value.value);
@@ -1979,6 +2011,7 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
gv.type = CUSTOM; gv.type = CUSTOM;
gv.data.customVal = malloc(sizeof(GroundObject)); gv.data.customVal = malloc(sizeof(GroundObject));
*gv.data.customVal = createObject(*gstruct); *gv.data.customVal = createObject(*gstruct);
gv.customType = gstruct;
break; break;
} }
case NONE: { case NONE: {

View File

@@ -137,6 +137,7 @@ static GroundInstType getInstructionType(const char* inst) {
if (strcmp(inst, "input") == 0 || strcmp(inst, "stdin") == 0) return INPUT; if (strcmp(inst, "input") == 0 || strcmp(inst, "stdin") == 0) return INPUT;
if (strcmp(inst, "print") == 0 || strcmp(inst, "stdout") == 0) return PRINT; if (strcmp(inst, "print") == 0 || strcmp(inst, "stdout") == 0) return PRINT;
if (strcmp(inst, "println") == 0 || strcmp(inst, "stdlnout") == 0) return PRINTLN; if (strcmp(inst, "println") == 0 || strcmp(inst, "stdlnout") == 0) return PRINTLN;
if (strcmp(inst, "error") == 0) return ERRORCMD;
if (strcmp(inst, "set") == 0) return SET; if (strcmp(inst, "set") == 0) return SET;
if (strcmp(inst, "gettype") == 0) return GETTYPE; if (strcmp(inst, "gettype") == 0) return GETTYPE;
if (strcmp(inst, "exists") == 0) return EXISTS; if (strcmp(inst, "exists") == 0) return EXISTS;

View File

@@ -412,6 +412,9 @@ void printGroundInstruction(GroundInstruction* gi) {
break; break;
case CREATELABEL: case CREATELABEL:
break; break;
case ERRORCMD:
printf("error");
break;
default: default:
printf("FIXME"); printf("FIXME");
break; break;
@@ -582,3 +585,43 @@ GroundError createGroundError(char* what, char* type, GroundInstruction* where,
return ge; return ge;
} }
bool checkFnTypes(GroundValue* left, GroundFunctionArgs* right) {
if (left->type != right->type) {
return false;
}
if (left->type == CUSTOM) {
if (left->customType->size != right->customType->size) {
return false;
}
for (size_t i = 0; i < left->customType->size; i++) {
if (strcmp(left->customType->fields[i].id, right->customType->fields[i].id) != 0) {
return false;
}
if (!checkTypes(&left->customType->fields[i].value, &right->customType->fields[i].value)) {
return false;
}
}
}
return true;
}
bool checkTypes(GroundValue* left, GroundValue* right) {
if (left->type != right->type) {
return false;
}
if (left->type == CUSTOM) {
if (left->customType->size != right->customType->size) {
return false;
}
for (size_t i = 0; i < left->customType->size; i++) {
if (strcmp(left->customType->fields[i].id, right->customType->fields[i].id) != 0) {
return false;
}
if (!checkTypes(&left->customType->fields[i].value, &right->customType->fields[i].value)) {
return false;
}
}
}
return true;
}

View File

@@ -9,7 +9,7 @@
#include "include/uthash.h" #include "include/uthash.h"
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, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, USE, EXTERN, CREATELABEL, PAUSE, DROP 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, STOI, STOD, TOSTRING, FUN, RETURN, ENDFUN, PUSHARG, CALL, STRUCT, ENDSTRUCT, INIT, USE, EXTERN, CREATELABEL, PAUSE, DROP, ERRORCMD
} GroundInstType; } GroundInstType;
typedef enum GroundValueType { typedef enum GroundValueType {
@@ -62,6 +62,7 @@ typedef struct GroundError {
*/ */
typedef struct GroundValue { typedef struct GroundValue {
GroundValueType type; GroundValueType type;
struct GroundStruct* customType;
union { union {
int64_t intVal; int64_t intVal;
double doubleVal; double doubleVal;
@@ -125,6 +126,7 @@ typedef struct GroundProgram {
*/ */
typedef struct GroundFunctionArgs { typedef struct GroundFunctionArgs {
GroundValueType type; GroundValueType type;
struct GroundStruct* customType;
char* name; char* name;
} GroundFunctionArgs; } GroundFunctionArgs;
@@ -276,6 +278,11 @@ void freeGroundObject(GroundObject* object);
// Creates a GroundError. // Creates a GroundError.
GroundError createGroundError(char* what, char* type, GroundInstruction* where, size_t* line); GroundError createGroundError(char* what, char* type, GroundInstruction* where, size_t* line);
// Compares types of a value and function args.
bool checkFnTypes(GroundValue* left, GroundFunctionArgs* arg);
// Compares types of two values.
bool checkTypes(GroundValue* left, GroundValue* right);
#endif #endif

2
tests/error.grnd Normal file
View File

@@ -0,0 +1,2 @@
setlist &dat 1 2 3 "Hi!"
error "Hello" $dat 1