Fix bugs
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
25
src/types.c
25
src/types.c
@@ -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));
|
||||
|
||||
@@ -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
9
tests/to1000.grnd
Normal 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
|
||||
Reference in New Issue
Block a user