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 add_executable(groundc
src/main.c src/main.c
src/interpreter.c
src/interpreter.h
src/parser.c src/parser.c
src/parser.h src/parser.h
src/lexer.c src/lexer.c

View File

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

View File

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

View File

@@ -142,8 +142,33 @@ void freeGroundInstruction(GroundInstruction* gi) {
for (size_t i = 0; i < gi-> args.length; i++) { for (size_t i = 0; i < gi-> args.length; i++) {
freeGroundArg(&gi->args.args[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) { void addArgToInstruction(GroundInstruction* gi, GroundArg arg) {
gi->args.length ++; gi->args.length ++;
GroundArg* newArgs = realloc(gi->args.args, gi->args.length * sizeof(GroundArg)); 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. // Frees all data stored on the heap in a GroundInstruction.
void freeGroundInstruction(GroundInstruction* gi); void freeGroundInstruction(GroundInstruction* gi);
// Creates a deep copy of a GroundInstruction.
GroundInstruction copyGroundInstruction(const GroundInstruction* gi);
// Adds arg (arg) to the GroundInstruction (gi). // Adds arg (arg) to the GroundInstruction (gi).
void addArgToInstruction(GroundInstruction* gi, GroundArg arg); 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