Labels and control flow
This commit is contained in:
@@ -22,9 +22,9 @@ Progress marker:
|
||||
- [x] Values
|
||||
- [x] References
|
||||
- [ ] Interpreter
|
||||
- [ ] Labels
|
||||
- [x] Labels
|
||||
- [ ] Console I/O
|
||||
- [ ] Control flow
|
||||
- [x] Control flow
|
||||
- [ ] Data
|
||||
- [ ] Variable creation
|
||||
- [ ] Variable access
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
int currentInstruction = 0;
|
||||
|
||||
GroundLabel* labels = NULL;
|
||||
|
||||
void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where, int whereLine) {
|
||||
printf("Ground runtime error:\n ErrorType: ");
|
||||
switch (error) {
|
||||
@@ -41,11 +43,37 @@ 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);
|
||||
return item;
|
||||
}
|
||||
|
||||
void deleteLabel(GroundLabel** head, GroundLabel *item) {
|
||||
HASH_DEL(*head, item);
|
||||
free(item);
|
||||
}
|
||||
|
||||
void delete_all(GroundLabel **head) {
|
||||
GroundLabel *current, *tmp;
|
||||
HASH_ITER(hh, *head, current, tmp) {
|
||||
HASH_DEL(*head, current);
|
||||
free(current);
|
||||
}
|
||||
}
|
||||
|
||||
void interpretGroundProgram(GroundProgram* in) {
|
||||
// Preprocess all labels
|
||||
for (int i = 0; i < in->size; i++) {
|
||||
if (in->instructions[i].type == CREATELABEL) {
|
||||
// labelHashmap.addLabel()
|
||||
addLabel(&labels, in->instructions[i].args.args[0].value.refName, i);
|
||||
}
|
||||
}
|
||||
while (currentInstruction < in->size) {
|
||||
@@ -61,6 +89,54 @@ void interpretGroundInstruction(GroundInstruction* in) {
|
||||
case CREATELABEL: {
|
||||
break;
|
||||
}
|
||||
case IF: {
|
||||
if (in->args.length < 2) {
|
||||
runtimeError(TOO_FEW_ARGS, "Expecting 2 arguments", in, currentInstruction);
|
||||
}
|
||||
if (in->args.length > 2) {
|
||||
runtimeError(TOO_MANY_ARGS, "Expecting 2 arguments", in, currentInstruction);
|
||||
}
|
||||
if (in->args.args[0].type != VALUE && in->args.args[0].value.value.type != BOOL) {
|
||||
runtimeError(ARG_TYPE_MISMATCH, "Expecting a bool for arg 0", in, currentInstruction);
|
||||
}
|
||||
if (in->args.args[0].type != LINEREF) {
|
||||
runtimeError(ARG_TYPE_MISMATCH, "Expecting a LineRef for arg 1", in, currentInstruction);
|
||||
}
|
||||
|
||||
if (in->args.args[0].value.value.data.boolVal) {
|
||||
GroundLabel* label = findLabel(labels, in->args.args[1].value.refName);
|
||||
if (label) {
|
||||
currentInstruction = label->lineNum;
|
||||
} else {
|
||||
runtimeError(UNKNOWN_LABEL, NULL, in, currentInstruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
case JUMP: {
|
||||
if (in->args.length < 1) {
|
||||
runtimeError(TOO_FEW_ARGS, "Expecting 1 argument", in, currentInstruction);
|
||||
}
|
||||
if (in->args.length > 1) {
|
||||
runtimeError(TOO_MANY_ARGS, "Expecting 1 argument", in, currentInstruction);
|
||||
}
|
||||
if (in->args.args[0].type != LINEREF) {
|
||||
runtimeError(ARG_TYPE_MISMATCH, "Expecting a LineRef for arg 1", in, currentInstruction);
|
||||
}
|
||||
|
||||
GroundLabel* label = findLabel(labels, in->args.args[0].value.refName);
|
||||
if (label) {
|
||||
currentInstruction = label->lineNum;
|
||||
} else {
|
||||
runtimeError(UNKNOWN_LABEL, NULL, in, currentInstruction);
|
||||
}
|
||||
}
|
||||
case END: {
|
||||
if (in->args.length < 1) {
|
||||
exit(0);
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PRINT: {
|
||||
if (in->args.length < 1) {
|
||||
runtimeError(TOO_FEW_ARGS, NULL, in, currentInstruction);
|
||||
@@ -82,13 +158,6 @@ void interpretGroundInstruction(GroundInstruction* in) {
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
case END: {
|
||||
if (in->args.length < 1) {
|
||||
exit(0);
|
||||
} else {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
#ifndef INTERPRETER_H
|
||||
#define INTERPRETER_H
|
||||
#define MAX_ID_LEN 64
|
||||
|
||||
#include "types.h"
|
||||
#include "parser.h"
|
||||
#include "include/uthash.h"
|
||||
|
||||
typedef enum GroundRuntimeError {
|
||||
ARG_TYPE_MISMATCH, TOO_FEW_ARGS, TOO_MANY_ARGS, FIXME
|
||||
ARG_TYPE_MISMATCH, TOO_FEW_ARGS, TOO_MANY_ARGS, UNKNOWN_LABEL, FIXME
|
||||
} GroundRuntimeError;
|
||||
|
||||
typedef struct GroundLabel {
|
||||
|
||||
char id[MAX_ID_LEN];
|
||||
int lineNum;
|
||||
UT_hash_handle hh;
|
||||
} GroundLabel;
|
||||
|
||||
void interpretGroundProgram(GroundProgram* in);
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
print
|
||||
@myLabel
|
||||
println "dingus"
|
||||
jump %myLabel
|
||||
|
||||
Reference in New Issue
Block a user