aboutsummaryrefslogtreecommitdiffstats
path: root/src/compiler.h
blob: 3fed075f08e29324736699e955bd9b8002de71a8 (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#ifndef BDL_COMPILER_H
#define BDL_COMPILER_H


#define PRELUDE_FILE "src/x86_64/prelude.asm"
#define POSTLUDE_FILE "src/x86_64/postlude.asm"

void compile_object(Object *obj);
void compile_fixnum(Object *obj);
void compile_proc_call(Object *obj);
void compile(Root *roots);

void
emit_file(char *file_name) {
    FILE *file = fopen(file_name, "r");
    if (!file) {
        fprintf(stderr, "error: couldn't open input file: %s\n", file_name);
        exit(EXIT_FAILURE);
    }
    char buf[1024];
    size_t n = 0;
    while ((n = fread(&buf, 1, 1024, file)) > 0) {
        fwrite(buf, 1, n, stdout);
    }
}

void
compile_fixnum(Object *obj) {
    printf("    ;; -- compile_fixnum --\n");
    printf("    mov     rax, %ld\n", obj->fixnum);
    printf("    push    rax\n");
    printf("    ;; --------------------\n");
}

typedef enum OpType {
    OP_ADD,
    OP_SUB,
    OP_MUL,
    OP_DIV,
    OP_MOD,
} OpType;

void
arithmetic_op(OpType type) {
    printf("    ;; -- arithmetic_op --\n");
    printf("    pop     rcx\n");
    printf("    pop     rax\n");
    switch (type) {
        case OP_ADD: {
            printf("    add     rax, rcx\n");
        } break;
        case OP_SUB: {
            printf("    sub     rax, rcx\n");
        } break;
        case OP_MUL: {
            printf("    mul     rcx\n");
        } break;
        case OP_DIV: {
            printf("    mov     rdx, 0\n");
            printf("    div     rcx\n");
        } break;
        case OP_MOD: {
            printf("    mov     rdx, 0\n");
            printf("    div     rcx\n");
            printf("    mov     rax, rdx\n");
        } break;
    }
    printf("    push    rax\n");
    printf("    ;; -------------------\n");
}

void
compile_proc_call(Object *obj) {
    printf("    ;; -- compile_proc_call --\n");
    OpType op;
    if (sv_equal(&obj->head->text, &STRING("+"))) { op = OP_ADD;}
    if (sv_equal(&obj->head->text, &STRING("-"))) { op = OP_SUB;}
    if (sv_equal(&obj->head->text, &STRING("*"))) { op = OP_MUL;}
    if (sv_equal(&obj->head->text, &STRING("/"))) { op = OP_DIV;}
    if (sv_equal(&obj->head->text, &STRING("%"))) { op = OP_MOD;}
    // TODO: Resolve function call.
    Object *args = obj->tail;
    // TODO: capture first operand in the accumulator. Number of arguments
    // checking should have been handled in the parser.
    compile_object(args->head);
    args = args->tail;
    while (args != NULL) {
        compile_object(args->head);
        args = args->tail;
        arithmetic_op(op);
    }
    printf("    ;; -----------------------\n");
}

void
compile_object(Object *obj) {
    switch (obj->type) {
        case OBJ_TYPE_FIXNUM: { compile_fixnum(obj); } break;
        case OBJ_TYPE_PAIR: { compile_proc_call(obj); } break;
        default: break;
    }
}

void
compile(Root *roots) {
    emit_file(PRELUDE_FILE);
    for (size_t i = 0; i < array_size(roots); i++) {
        Object *root = roots[i];
        compile_object(root);
        // OBJ_PRINT(root);
    }
    emit_file(POSTLUDE_FILE);
}

#endif // BDL_COMPILER_H