Fix bugs
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
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++) {
|
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));
|
||||||
|
|||||||
@@ -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
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