summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interpreter.c128
-rw-r--r--src/interpreter.h5
-rw-r--r--src/main.c9
-rw-r--r--src/program.c89
-rw-r--r--src/program.h50
-rw-r--r--src/stack.c47
-rw-r--r--src/tape.c44
-rw-r--r--src/types.h73
8 files changed, 238 insertions, 207 deletions
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 <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;
- }
+void interpret(Program* program) {
+ Stack tape_stack;
+ stack_init(&tape_stack, sizeof(void*));
- if (count == 0) {
- return;
- };
- }
-}
+ Tape* tape = malloc(sizeof(Tape));
+ tape_init(tape, sizeof(void*));
-static void recurse_program(Program* program, Tape* tape) {
+ stack_push(&tape_stack, 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 <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
-#include <stdint.h>
#include <string.h>
#include <errno.h>
@@ -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 <stdio.h>
#include <stdlib.h>
-#include <stdint.h>
#include <string.h>
#include <errno.h>
+#include <stdbool.h>
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);
- program->index++;
-}
-
-void program_last(Program* program, Symbol* symbol) {
- if (program->index < 1) {
- *symbol = Eof;
- return;
- }
- program->index--;
- program_peek(program, symbol);
-}
-
-void program_free(Program* program) {
- free(program->data);
+ *symbol = program->data[program->index].s;
}
-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--;
+uint32_t program_get_jump(Program* program) {
+ if (program->index >= program->len) {
+ return 0;
}
+ return program->data[program->index].j;
}
-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;
+void program_next(Program* program) {
+ program->index++;
}
-uint8_t* tape_ptr(Tape* tape) {
- return tape->data + tape->index;
+void program_seek(Program* program, uint32_t index) {
+ program->index = index;
}
-void tape_free(Tape* tape) {
- free(tape->data);
+void program_free(Program* program) {
+ free(program->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 <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-
-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 <stdlib.h>
+
+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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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 <stdint.h>
+#include <stdio.h>
+
+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);