Labels and control flow

This commit is contained in:
2025-11-23 19:18:10 +11:00
parent a69901be7b
commit ddcde88182
4 changed files with 87 additions and 13 deletions

View File

@@ -22,9 +22,9 @@ Progress marker:
- [x] Values - [x] Values
- [x] References - [x] References
- [ ] Interpreter - [ ] Interpreter
- [ ] Labels - [x] Labels
- [ ] Console I/O - [ ] Console I/O
- [ ] Control flow - [x] Control flow
- [ ] Data - [ ] Data
- [ ] Variable creation - [ ] Variable creation
- [ ] Variable access - [ ] Variable access

View File

@@ -6,6 +6,8 @@
int currentInstruction = 0; int currentInstruction = 0;
GroundLabel* labels = NULL;
void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where, int whereLine) { void runtimeError(GroundRuntimeError error, char* what, GroundInstruction* where, int whereLine) {
printf("Ground runtime error:\n ErrorType: "); printf("Ground runtime error:\n ErrorType: ");
switch (error) { switch (error) {
@@ -41,11 +43,37 @@ 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 *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) { void interpretGroundProgram(GroundProgram* in) {
// Preprocess all labels // Preprocess all labels
for (int i = 0; i < in->size; i++) { for (int i = 0; i < in->size; i++) {
if (in->instructions[i].type == CREATELABEL) { if (in->instructions[i].type == CREATELABEL) {
// labelHashmap.addLabel() addLabel(&labels, in->instructions[i].args.args[0].value.refName, i);
} }
} }
while (currentInstruction < in->size) { while (currentInstruction < in->size) {
@@ -61,6 +89,54 @@ void interpretGroundInstruction(GroundInstruction* in) {
case CREATELABEL: { case CREATELABEL: {
break; 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: { case PRINT: {
if (in->args.length < 1) { if (in->args.length < 1) {
runtimeError(TOO_FEW_ARGS, NULL, in, currentInstruction); runtimeError(TOO_FEW_ARGS, NULL, in, currentInstruction);
@@ -82,13 +158,6 @@ void interpretGroundInstruction(GroundInstruction* in) {
printf("\n"); printf("\n");
break; break;
} }
case END: {
if (in->args.length < 1) {
exit(0);
} else {
}
break;
}
default: { default: {
runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction); runtimeError(FIXME, "Currently unimplemented instruction", in, currentInstruction);
} }

View File

@@ -1,16 +1,19 @@
#ifndef INTERPRETER_H #ifndef INTERPRETER_H
#define INTERPRETER_H #define INTERPRETER_H
#define MAX_ID_LEN 64
#include "types.h" #include "types.h"
#include "parser.h" #include "parser.h"
#include "include/uthash.h" #include "include/uthash.h"
typedef enum GroundRuntimeError { 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; } GroundRuntimeError;
typedef struct GroundLabel { typedef struct GroundLabel {
char id[MAX_ID_LEN];
int lineNum;
UT_hash_handle hh;
} GroundLabel; } GroundLabel;
void interpretGroundProgram(GroundProgram* in); void interpretGroundProgram(GroundProgram* in);

View File

@@ -1 +1,3 @@
print @myLabel
println "dingus"
jump %myLabel