From 0f0862245f0a73c589116eb401b0eeaab5c5e780 Mon Sep 17 00:00:00 2001 From: Aryadev Chavali Date: Tue, 3 Dec 2024 03:40:41 +0000 Subject: Build two executables: obi and obc The names stand for Oreo's Brainfuck Interpreter and Oreo's Brainfuck Compiler, separate tasks that shouldn't be packaged in one executable. --- obi.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 obi.c (limited to 'obi.c') diff --git a/obi.c b/obi.c new file mode 100644 index 0000000..72cff00 --- /dev/null +++ b/obi.c @@ -0,0 +1,151 @@ +/* obi.c + * Created: 2023-09-02 + * Author: Aryadev Chavali + * Description: Entrypoint of interpreter + */ + +#include +#include +#include +#include +#include + +#include "./lib.h" +#include "./parser.h" + +#define MIN_MEM_DUMP 64 + +typedef struct +{ + size_t dp; + uint8_t memory[MEMORY_DEFAULT]; + +#ifdef DEBUG + size_t dp_max; +#endif +} machine_t; + +void interpret(machine_t *cpu, node_t *ast, size_t num) +{ + for (size_t i = 0; i < num; ++i) + { + node_t node = ast[i]; + switch (node.type) + { + case NEXT: + ++cpu->dp; + break; + case PREV: + --cpu->dp; + break; + case INC: + ++cpu->memory[cpu->dp]; + break; + case DEC: + --cpu->memory[cpu->dp]; + break; + case OUT: + putchar(cpu->memory[cpu->dp]); + break; + case READ: + cpu->memory[cpu->dp] = getchar(); + break; + case LIN: + if (cpu->memory[cpu->dp] == 0) + i = node.loop_ref; + break; + case LOUT: + if (cpu->memory[cpu->dp] != 0) + i = node.loop_ref; + break; + } +#ifdef DEBUG + if (cpu->dp > cpu->dp_max) + cpu->dp_max = cpu->dp + 1; +#endif + } + +#ifdef DEBUG + if (cpu->dp_max < MIN_MEM_DUMP) + cpu->dp_max = MIN_MEM_DUMP; +#endif +} + +void usage(const char *name, FILE *fp) +{ + fprintf(fp, + "Usage: %s [FILE]...\n\tInterprets FILE as a brainfuck program" + "\n", + name); +} + +int main(int argc, char *argv[]) +{ + if (argc == 1) + { + usage(argv[0], stderr); + return 1; + } + + int ret = 0; + char *filepath = argv[1], *file_data = NULL; + buffer_t *buffer = NULL; + struct PResult res = {0}; + machine_t machine = {0}; + + FILE *handle = fopen(filepath, "r"); +#ifdef DEBUG + printf("[DEBUG]: Attempting to open file handle to %s\n", filepath); +#endif + if (!handle) + { + fprintf(stderr, "ERROR: Could not open \"%s\"\n", filepath); + ret = 1; + goto end; + } + file_data = fread_all(handle); + fclose(handle); +#ifdef DEBUG + printf("[DEBUG]: Read data from file %s\n", filepath); +#endif + + buffer = buffer_init_str(filepath, file_data, strlen(file_data)); +#ifdef DEBUG + puts("[DEBUG]: Initialised buffer"); +#endif + res = parse_buffer(buffer); + if (res.nodes == NULL) + { + fputs("Exiting early...\n", stderr); + ret = 1; + goto end; + } + +#ifdef DEBUG + char *str = ast_to_str(res.nodes, res.size); + printf("[DEBUG]: Parsed buffer (%lu nodes parsed)\n\t[DEBUG]: Out=%s\n", + res.size, str); + free(str); +#endif + + interpret(&machine, res.nodes, res.size); + +#ifdef DEBUG + printf("[DEBUG]: Finished interpreting, memory:"); + for (size_t i = 0; i < machine.dp_max; ++i) + { + if (i % 8 == 0) + printf("\n\t"); + printf("%d ", machine.memory[i]); + } + printf("\n"); +#endif +end: + if (res.nodes) + free(res.nodes); + if (buffer) + free(buffer); + if (file_data) + free(file_data); + return ret; +} -- cgit v1.2.3-13-gbd6f