diff options
Diffstat (limited to 'src/interpreter.c')
-rw-r--r-- | src/interpreter.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/interpreter.c b/src/interpreter.c new file mode 100644 index 0000000..f14abcc --- /dev/null +++ b/src/interpreter.c @@ -0,0 +1,136 @@ +#include "interpreter.h" +#include "program.h" + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static void loop_end(Program* program) { + uint32_t count = 1; + Symbol s; + + while (true) { + program_next(program, &s); + if (s == StartLoop) { + count++; + } else if (s == EndLoop) { + count--; + } else if (s == Eof) { + return; + } + + if (count == 0) return; + } +} + +static void loop_start(Program* program) { + uint32_t count = 1; + Symbol s; + + program_last(program, &s); + while (true) { + program_last(program, &s); + if (s == StartLoop) { + count--; + } else if (s == EndLoop) { + count++; + } else if (s == Eof) { + return; + } + + if (count == 0) { + return; + }; + } +} + +static void recurse_program(Program* program, Tape* tape) { + Symbol s; + +next: + program_next(program, &s); + + switch (s) { + case MoveLeft: + tape_left(tape); + break; + case MoveRight: + tape_right(tape); + break; + case Increment: + tape_set(tape, tape_get(tape) + 1); + break; + case Decrement: + tape_set(tape, tape_get(tape) - 1); + break; + case StartLoop: + if (tape_get(tape) == 0) + loop_end(program); + break; + case EndLoop: + if (tape_get(tape) != 0) + loop_start(program); + break; + case PutChar: { + printf("%c", tape_get(tape)); + break; + } + case GetChar: { + uint8_t c = (uint8_t) getchar(); + tape_set(tape, c); + break; + } + case Allocate: { + uint8_t len = tape_get(tape); + Tape* new = malloc(sizeof(Tape)); + tape_init(len, tape); + void* ptr = (void*) tape_ptr(tape); + memcpy(ptr, &new, sizeof(Tape*)); + break; + } + case Free: { + Tape* old; + void* ptr = (void*) tape_ptr(tape); + memcpy(&old, ptr, sizeof(Tape*)); + memset(ptr, 0, sizeof(Tape*)); + free(old); + break; + } + case EnterTape: { + Tape* cur; + void* ptr = (void*) tape_ptr(tape); + memcpy(&cur, ptr, sizeof(Tape*)); + recurse_program(program, cur); + break; + } + case GetString: { + uint8_t len = tape_get(tape); + void* ptr = (void*) tape_ptr(tape); + fgets(ptr, len, stdin); + break; + } + case PutString: { + char* ptr = (char*) tape_ptr(tape); + printf("%s", ptr); + break; + } + case Clear: + printf("\033c"); + break; + case LeaveTape: + case Eof: + case Invalid: + return; + } + + goto next; +} + +void run_program(Program* program) { + Tape tape; + tape_init(sizeof(void*), &tape); + recurse_program(program, &tape); + tape_free(&tape); +} |