summaryrefslogtreecommitdiff
path: root/src/interpreter.c
blob: 273d985803618eebe6657ca4f158737c16c4ad12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "types.h"

#include <stddef.h>
#include <stdlib.h>
#include <string.h>

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;
next:
    program_get(program, &s);
    
    switch (s) {
        case MoveLeft:
            tape_left(tape);
            break;
        case MoveRight:
            tape_right(tape);
            break;
        case Increment:
            tape_increment(tape);
            break;
        case Decrement:
            tape_decrement(tape);
            break;
        case StartLoop:
            if (tape_get(tape) == 0) {
                program_seek(program, program_get_jump(program));
            }
            break;
        case EndLoop:
            if (tape_get(tape) != 0) {
                program_seek(program, program_get_jump(program));
            }
            break;
        case PutChar: {
            printf("%c", tape_get(tape));
            break;
        }
        case GetChar: {
            tape_set(tape, getchar());
            break;
        }
        case Allocate: {
            Tape* new = malloc(sizeof(Tape));
            tape_init(new, tape_get(tape));
            memcpy(tape_ptr(tape), &new, sizeof(Tape*));
            break;
        }
        case Free: {
            Tape* old;
            memcpy(&old, tape_ptr(tape), sizeof(Tape*));
            tape_free(old);
            free(old);
            break;
        }
        case EnterTape: {
            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: {
            fgets((char*) tape_ptr(tape), tape_get(tape), stdin);
            break;
        }
        case PutString: {
            printf("%s", (char*) tape_ptr(tape));
            break;
        }
        case Clear:
            printf("\033c");
            break;
        case Eof:
            goto end;
    }

    program_next(program);
    goto next;
end:
    tape_free(tape);
    free(tape);

    stack_free(&tape_stack);
}