summaryrefslogtreecommitdiff
path: root/src/interpreter.c
diff options
context:
space:
mode:
authorTyler Murphy <tylerm@tylerm.dev>2023-04-13 17:04:05 -0400
committerTyler Murphy <tylerm@tylerm.dev>2023-04-13 17:04:05 -0400
commitfafd290ed990aa2bef34b44fe373175eb6133093 (patch)
tree5d4848b3006bc4eec5d5f49d6372516e1a2a0ba3 /src/interpreter.c
downloadbrainfucked-fafd290ed990aa2bef34b44fe373175eb6133093.tar.gz
brainfucked-fafd290ed990aa2bef34b44fe373175eb6133093.tar.bz2
brainfucked-fafd290ed990aa2bef34b44fe373175eb6133093.zip
brainfucked
Diffstat (limited to 'src/interpreter.c')
-rw-r--r--src/interpreter.c136
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);
+}