#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