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
|