diff --git a/src/interpreter.c b/src/interpreter.c index ed5c8fd..273d985 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -1,71 +1,22 @@ -#include "interpreter.h" -#include "program.h" +#include "types.h" #include -#include -#include #include #include -static void loop_end(Program* program) { - uint32_t count = 1; +void interpret(Program* program) { + Stack tape_stack; + stack_init(&tape_stack, sizeof(void*)); + + Tape* tape = malloc(sizeof(Tape)); + tape_init(tape, sizeof(void*)); + + stack_push(&tape_stack, tape); + 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); - - // printf("["); - // for(uint32_t i = 0; i < tape->len; i++) { - // printf("0x%02x ", tape->data[i]); - // } - // printf("\b]\n "); - // for(uint32_t i = 0; i < tape->len; i++) { - // if (i == tape->index) { - // printf(" ^ "); - // } else { - // printf(" "); - // } - // } - // printf(" \ + tape->indexn"); - + program_get(program, &s); + switch (s) { case MoveLeft: tape_left(tape); @@ -74,77 +25,72 @@ next: tape_right(tape); break; case Increment: - tape_set(tape, tape_get(tape) + 1); + tape_increment(tape); break; case Decrement: - tape_set(tape, tape_get(tape) - 1); + tape_decrement(tape); break; case StartLoop: - if (tape_get(tape) == 0) - loop_end(program); + if (tape_get(tape) == 0) { + program_seek(program, program_get_jump(program)); + } break; case EndLoop: - if (tape_get(tape) != 0) - loop_start(program); + if (tape_get(tape) != 0) { + program_seek(program, program_get_jump(program)); + } break; case PutChar: { printf("%c", tape_get(tape)); break; } case GetChar: { - uint8_t c = (uint8_t) getchar(); - tape_set(tape, c); + tape_set(tape, getchar()); break; } case Allocate: { - uint8_t len = tape_get(tape); Tape* new = malloc(sizeof(Tape)); - tape_init(len, new); - void* ptr = (void*) tape_ptr(tape); - memcpy(ptr, &new, sizeof(Tape*)); + tape_init(new, tape_get(tape)); + memcpy(tape_ptr(tape), &new, sizeof(Tape*)); break; } case Free: { Tape* old; - void* ptr = (void*) tape_ptr(tape); - memcpy(&old, ptr, sizeof(Tape*)); - memset(ptr, 0, sizeof(Tape*)); + memcpy(&old, tape_ptr(tape), sizeof(Tape*)); tape_free(old); free(old); break; } case EnterTape: { - Tape* cur; - void* ptr = (void*) tape_ptr(tape); - memcpy(&cur, ptr, sizeof(Tape*)); - recurse_program(program, cur); + memcpy(&tape, tape_ptr(tape), sizeof(Tape*)); + stack_push(&tape_stack, tape); + break; + } + case LeaveTape: { + tape = stack_pop(&tape_stack); + if (tape == NULL) goto end; break; } case GetString: { - uint8_t len = tape_get(tape); - void* ptr = (void*) tape_ptr(tape); - fgets(ptr, len, stdin); + fgets((char*) tape_ptr(tape), tape_get(tape), stdin); break; } case PutString: { - char* ptr = (char*) tape_ptr(tape); - printf("%s", ptr); + printf("%s", (char*) tape_ptr(tape)); break; } case Clear: printf("\033c"); break; - case LeaveTape: case Eof: - return; + goto end; } + program_next(program); goto next; -} +end: + tape_free(tape); + free(tape); -void run_program(Program* program) { - Tape tape; - tape_init(sizeof(void*), &tape); - recurse_program(program, &tape); - tape_free(&tape); + stack_free(&tape_stack); } diff --git a/src/interpreter.h b/src/interpreter.h deleted file mode 100644 index b7c3e2a..0000000 --- a/src/interpreter.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "program.h" - -void run_program(Program* program); diff --git a/src/main.c b/src/main.c index 20134cd..c51a88f 100644 --- a/src/main.c +++ b/src/main.c @@ -1,10 +1,7 @@ -#include "program.h" -#include "interpreter.h" +#include "types.h" -#include #include #include -#include #include #include @@ -42,8 +39,8 @@ int main(int argc, char** argv) { } Program program; - program_init(file, &program); - run_program(&program); + program_init(&program, file); + interpret(&program); program_free(&program); return EXIT_SUCCESS; diff --git a/src/program.c b/src/program.c index 1d94da3..0fac9d5 100644 --- a/src/program.c +++ b/src/program.c @@ -1,10 +1,9 @@ -#include "program.h" +#include "types.h" -#include #include -#include #include #include +#include static char next_char(FILE* file) { char c; @@ -65,89 +64,69 @@ retest: } } -void program_init(FILE* file, Program* program) { +void program_init(Program* program, FILE* file) { uint32_t capacity = 8; - program->data = malloc(capacity * sizeof(Symbol)); + program->data = malloc(capacity * sizeof(struct instruction)); program->len = 0; program->index = 0; + Stack stack; + stack_init(&stack, 8); + Symbol s; while(true) { s = next_symbol(file); if (program->len == capacity) { capacity *= 2; - program->data = realloc(program->data, capacity * sizeof(Symbol)); + program->data = realloc(program->data, capacity * sizeof(struct instruction)); + } + + program->data[program->len].s = s; + program->data[program->len].j = 0; + + if (s == StartLoop) { + stack_pushi(&stack, program->len); + } else if (s == EndLoop) { + uint32_t i = stack_popi(&stack); + program->data[program->len].j = i; + if (i != 0 || program->data[i].j == 0) { + program->data[i].j = program->len; + } } - program->data[program->len] = s; program->len++; if (s == Eof) break; } - + stack_free(&stack); fclose(file); } -void program_peek(Program* program, Symbol* symbol) { - *symbol = program->data[program->index]; -} - -void program_next(Program* program, Symbol* symbol) { +void program_get(Program* program, Symbol* symbol) { if (program->index >= program->len) { *symbol = Eof; return; } - program_peek(program, symbol); + *symbol = program->data[program->index].s; +} + +uint32_t program_get_jump(Program* program) { + if (program->index >= program->len) { + return 0; + } + return program->data[program->index].j; +} + +void program_next(Program* program) { program->index++; } -void program_last(Program* program, Symbol* symbol) { - if (program->index < 1) { - *symbol = Eof; - return; - } - program->index--; - program_peek(program, symbol); +void program_seek(Program* program, uint32_t index) { + program->index = index; } void program_free(Program* program) { free(program->data); } - -void tape_init(uint32_t len, Tape* tape) { - tape->len = len; - tape->data = malloc(len); - tape->index = 0; - memset(tape->data, 0, len); -} - -void tape_left(Tape* tape) { - if (tape->index == 0) { - tape->index = tape->len - 1; - } else { - tape->index--; - } -} - -void tape_right(Tape* tape) { - tape->index++; - tape->index %= tape->len; -} - -uint8_t tape_get(Tape* tape) { - return tape->data[tape->index]; -} - -void tape_set(Tape* tape, uint8_t value) { - tape->data[tape->index] = value; -} - -uint8_t* tape_ptr(Tape* tape) { - return tape->data + tape->index; -} - -void tape_free(Tape* tape) { - free(tape->data); -} diff --git a/src/program.h b/src/program.h deleted file mode 100644 index ea29b6c..0000000 --- a/src/program.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include -#include - -typedef enum { - MoveLeft, - MoveRight, - Increment, - Decrement, - StartLoop, - EndLoop, - PutChar, - GetChar, - Allocate, - Free, - EnterTape, - LeaveTape, - PutString, - GetString, - Clear, - Eof -} Symbol; - -typedef struct { - uint32_t len; - uint32_t index; - Symbol* data; -} Program; - -void program_init(FILE* file, Program* program); -void program_peek(Program* program, Symbol* symbol); -void program_next(Program* program, Symbol* symbol); -void program_last(Program* program, Symbol* symbol); -void program_free(Program* program); - -typedef struct { - uint32_t len; - uint32_t index; - uint8_t* data; -} Tape; - -void tape_init(uint32_t len, Tape* tape); -void tape_left(Tape* tape); -void tape_right(Tape* tape); -uint8_t tape_get(Tape* tape); -void tape_set(Tape* tape, uint8_t value); -uint8_t* tape_ptr(Tape* tape); -void tape_free(Tape* tape); diff --git a/src/stack.c b/src/stack.c new file mode 100644 index 0000000..3491581 --- /dev/null +++ b/src/stack.c @@ -0,0 +1,47 @@ +#include "types.h" + +#include + +void stack_init(Stack* stack, uint32_t len) { + stack->index = 0; + stack->len = len; + stack->data = malloc(stack->len * sizeof(union stored)); +} + +void stack_push(Stack* stack, void* value) { + if (stack->index == stack->len) { + stack->len *= 2; + stack->data = realloc(stack->data, stack->len * sizeof(union stored)); + } + stack->data[stack->index].p = value; + stack->index++; +} + +void* stack_pop(Stack* stack) { + if (stack->index == 0) { + return NULL; + } + stack->index--; + return stack->data[stack->index].p; +} + +void stack_pushi(Stack* stack, uint32_t value) { + if (stack->index == stack->len) { + stack->len *= 2; + stack->data = realloc(stack->data, stack->len * sizeof(union stored)); + } + stack->data[stack->index].i = value; + stack->index++; +} + +uint32_t stack_popi(Stack* stack) { + if (stack->index == 0) { + return 0; + } + stack->index--; + return stack->data[stack->index].i; +} + +void stack_free(Stack* stack) { + free(stack->data); +} diff --git a/src/tape.c b/src/tape.c new file mode 100644 index 0000000..8718cfd --- /dev/null +++ b/src/tape.c @@ -0,0 +1,44 @@ +#include "types.h" + +#include +#include +#include + +void tape_init(Tape* tape, uint8_t len) { + tape->index = 0; + tape->len = len; + tape->data = malloc(tape->len); + memset(tape->data, 0, len); +} + +void tape_free(Tape* tape) { + free(tape->data); +} + +void tape_left(Tape* tape) { + tape->index--; +} + +void tape_right(Tape* tape) { + tape->index++; +} + +void tape_increment(Tape* tape) { + tape->data[tape->index]++; +} + +void tape_decrement(Tape* tape) { + tape->data[tape->index]--; +} + +uint8_t tape_get(Tape* tape) { + return tape->data[tape->index]; +} + +void tape_set(Tape* tape, uint8_t value) { + tape->data[tape->index] = value; +} + +void* tape_ptr(Tape* tape) { + return tape->data + tape->index; +} diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..413d313 --- /dev/null +++ b/src/types.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include + +typedef enum { + MoveLeft, + MoveRight, + Increment, + Decrement, + StartLoop, + EndLoop, + PutChar, + GetChar, + Allocate, + Free, + EnterTape, + LeaveTape, + PutString, + GetString, + Clear, + Eof +} Symbol; + +typedef struct { + uint32_t len; + uint32_t index; + struct instruction { + Symbol s; + uint32_t j; + } * data; +} Program; + +void program_init(Program* program, FILE* file); +void program_get(Program* program, Symbol* symbol); +uint32_t program_get_jump(Program* program); +void program_next(Program* program); +void program_seek(Program* program, uint32_t index); +void program_free(Program* program); + +typedef struct { + uint32_t len; + uint32_t index; + union stored { + void* p; + uint32_t i; + } * data; +} Stack; + +void stack_init(Stack* stack, uint32_t len); +void stack_push(Stack* stack, void* value); +void* stack_pop(Stack* stack); +void stack_pushi(Stack* stack, uint32_t value); +uint32_t stack_popi(Stack* stack); +void stack_free(Stack* stack); + +typedef struct { + uint8_t len; + uint8_t index; + uint8_t* data; +} Tape; + +void tape_init(Tape* tape, uint8_t len); +void tape_free(Tape* tape); +void tape_left(Tape* tape); +void tape_right(Tape* tape); +void tape_increment(Tape* tape); +void tape_decrement(Tape* tape); +uint8_t tape_get(Tape* tape); +void tape_set(Tape* tape, uint8_t value); +void* tape_ptr(Tape* tape); + +void interpret(Program* program);