This commit is contained in:
2025-11-24 10:15:53 +11:00
parent 251dd719b0
commit 51e9df75c3
6 changed files with 127 additions and 16 deletions

View File

@@ -7,6 +7,8 @@ include_directories(src)
add_executable(groundc
src/main.c
src/interpreter.c
src/interpreter.h
src/parser.c
src/parser.h
src/lexer.c

View File

@@ -50,13 +50,6 @@ void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where
exit(1);
}
void addLabel(GroundLabel **head, const char *id, int data) {
GroundLabel* item = malloc(sizeof(GroundLabel));
snprintf(item->id, MAX_ID_LEN, "%s", id);
item->lineNum = data;
HASH_ADD_STR(*head, id, item);
}
GroundLabel* findLabel(GroundLabel* head, const char *id) {
GroundLabel *item;
HASH_FIND_STR(head, id, item);
@@ -68,10 +61,14 @@ void deleteLabel(GroundLabel** head, GroundLabel *item) {
free(item);
}
void addVariable(GroundVariable **head, const char *id, GroundValue data) {
GroundVariable* item = malloc(sizeof(GroundVariable));
void addLabel(GroundLabel **head, const char *id, int data) {
GroundLabel* label = findLabel(*head, id);
if (label) {
deleteLabel(head, label);
}
GroundLabel* item = malloc(sizeof(GroundLabel));
snprintf(item->id, MAX_ID_LEN, "%s", id);
item->value = data;
item->lineNum = data;
HASH_ADD_STR(*head, id, item);
}
@@ -86,6 +83,17 @@ void deleteVariable(GroundVariable** head, GroundVariable *item) {
free(item);
}
void addVariable(GroundVariable **head, const char *id, GroundValue data) {
GroundVariable* variable = findVariable(*head, id);
if (variable) {
deleteVariable(head, variable);
}
GroundVariable* item = malloc(sizeof(GroundVariable));
snprintf(item->id, MAX_ID_LEN, "%s", id);
item->value = data;
HASH_ADD_STR(*head, id, item);
}
void interpretGroundProgram(GroundProgram* in) {
GroundLabel* labels = NULL;
GroundVariable* variables = NULL;
@@ -100,18 +108,22 @@ void interpretGroundProgram(GroundProgram* in) {
}
}
while (currentInstruction < in->size) {
interpretGroundInstruction(&in->instructions[currentInstruction], &scope);
interpretGroundInstruction(in->instructions[currentInstruction], &scope);
currentInstruction++;
}
}
void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope) {
void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope) {
GroundInstruction copied_inst = copyGroundInstruction(&inst);
GroundInstruction* in = &copied_inst;
// Insert variables prefixed with $
for (int i = 0; i < in->args.length; i++) {
if (in->args.args[i].type == VALREF) {
GroundVariable* variable = findVariable(*scope->variables, in->args.args[0].value.refName);
GroundVariable* variable = findVariable(*scope->variables, in->args.args[i].value.refName);
if (variable) {
free(in->args.args[i].value.refName); // Free the strdup'd refName
in->args.args[i].value.value = variable->value;
in->args.args[i].type = VALUE;
} else {
@@ -239,7 +251,7 @@ void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope) {
if (right->type != STRING) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a String for arg 2", in, currentInstruction);
}
char* newString = malloc(sizeof(char));
char* newString = malloc(strlen(left->data.stringVal) + strlen(right->data.stringVal));
strcpy(newString, left->data.stringVal);
strcat(newString, right->data.stringVal);
@@ -261,7 +273,7 @@ void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope) {
if (right->type == INT) {
result += right->data.intVal;
} else if (left->type == DOUBLE) {
} else if (right->type == DOUBLE) {
result += right->data.doubleVal;
}
@@ -275,9 +287,67 @@ void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope) {
}
break;
}
case EQUAL: {
if (in->args.length < 3) {
runtimeError(TOO_FEW_ARGS, "Expecting 3 args", in, currentInstruction);
}
if (in->args.length > 3) {
runtimeError(TOO_MANY_ARGS, "Expecting 3 args", in, currentInstruction);
}
if (in->args.args[0].type != VALUE) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 1", in, currentInstruction);
}
if (in->args.args[1].type != VALUE) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a Value for arg 2", in, currentInstruction);
}
if (in->args.args[2].type != DIRREF) {
runtimeError(ARG_TYPE_MISMATCH, "Expecting a DirectRef for arg 3", in, currentInstruction);
}
GroundValue* left = &in->args.args[0].value.value;
GroundValue* right = &in->args.args[1].value.value;
if (left->type != right->type) {
addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(false));
} else {
switch (left->type) {
case INT: {
bool cond = (left->data.intVal == right->data.intVal);
addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond));
break;
}
case DOUBLE: {
bool cond = (left->data.doubleVal == right->data.doubleVal);
addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond));
break;
}
case STRING: {
bool cond = (strcmp(left->data.stringVal, right->data.stringVal) == 0);
addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond));
break;
}
case CHAR: {
bool cond = (left->data.charVal == right->data.charVal);
addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond));
break;
}
case BOOL: {
bool cond = (left->data.boolVal == right->data.boolVal);
addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(cond));
break;
}
default: {
addVariable(scope->variables, in->args.args[2].value.refName, createBoolGroundValue(false));
break;
}
}
}
break;
}
default: {
runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction);
}
}
freeGroundInstruction(in);
}

View File

@@ -28,5 +28,7 @@ typedef struct GroundScope {
} GroundScope;
void interpretGroundProgram(GroundProgram* in);
void interpretGroundInstruction(GroundInstruction* in, GroundScope* scope);
void interpretGroundInstruction(GroundInstruction inst, GroundScope* scope);
#endif

View File

@@ -142,8 +142,33 @@ void freeGroundInstruction(GroundInstruction* gi) {
for (size_t i = 0; i < gi-> args.length; i++) {
freeGroundArg(&gi->args.args[i]);
}
free(gi->args.args);
}
GroundInstruction copyGroundInstruction(const GroundInstruction* inst) {
GroundInstruction newInst;
newInst.type = inst->type;
newInst.args.length = inst->args.length;
if (inst->args.length > 0) {
newInst.args.args = malloc(inst->args.length * sizeof(GroundArg));
for (size_t i = 0; i < inst->args.length; i++) {
newInst.args.args[i].type = inst->args.args[i].type;
if (inst->args.args[i].type == VALUE) {
newInst.args.args[i].value.value = inst->args.args[i].value.value;
if (inst->args.args[i].value.value.type == STRING) {
newInst.args.args[i].value.value.data.stringVal = strdup(inst->args.args[i].value.value.data.stringVal);
}
} else {
newInst.args.args[i].value.refName = strdup(inst->args.args[i].value.refName);
}
}
} else {
newInst.args.args = NULL;
}
return newInst;
}
void addArgToInstruction(GroundInstruction* gi, GroundArg arg) {
gi->args.length ++;
GroundArg* newArgs = realloc(gi->args.args, gi->args.length * sizeof(GroundArg));

View File

@@ -116,6 +116,9 @@ GroundInstruction createGroundInstruction(GroundInstType type);
// Frees all data stored on the heap in a GroundInstruction.
void freeGroundInstruction(GroundInstruction* gi);
// Creates a deep copy of a GroundInstruction.
GroundInstruction copyGroundInstruction(const GroundInstruction* gi);
// Adds arg (arg) to the GroundInstruction (gi).
void addArgToInstruction(GroundInstruction* gi, GroundArg arg);

9
tests/to1000.grnd Normal file
View File

@@ -0,0 +1,9 @@
set &var 0
println "dingle"
@jump
add 1 $var &var
println $var
equal $var 1000000 &cond
if $cond %end
jump %jump
@end