From dca96d579fdf7eb747294fc786e89a08031fe003 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 2 Nov 2021 15:56:32 +0100 Subject: Add `not` primitive procedure --- src/compiler.h | 153 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 60 deletions(-) diff --git a/src/compiler.h b/src/compiler.h index 18e8a3e..76aec85 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -9,6 +9,8 @@ #define BOOL_MASK 3 #define BOOL_TAG 3 #define BOOL_SHIFT 2 +#define TRUE_VAL ((1 << BOOL_SHIFT) | BOOL_TAG) +#define FALSE_VAL ((0 << BOOL_SHIFT) | BOOL_TAG) #define FIXNUM_MASK 1 #define FIXNUM_TAG 0 #define FIXNUM_SHIFT 1 @@ -69,46 +71,17 @@ typedef enum OpType { OP_IS_ZERO, OP_IS_BOOL, OP_IS_FIXNUM, - // TODO: etc. + // Logic operations. + OP_NOT, + OP_AND, + OP_OR, + OP_EQUAL, + OP_GREATER, + OP_LESS, + OP_GREATER_EQ, + OP_LESS_EQL, } 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(" sar rax, %d\n", FIXNUM_SHIFT); - printf(" sar rcx, %d\n", FIXNUM_SHIFT); - printf(" mul rcx\n"); - printf(" sal rax, %d\n", FIXNUM_SHIFT); - } break; - case OP_DIV: { - printf(" sar rax, %d\n", FIXNUM_SHIFT); - printf(" sar rcx, %d\n", FIXNUM_SHIFT); - printf(" mov rdx, 0\n"); - printf(" div rcx\n"); - printf(" sal rax, %d\n", FIXNUM_SHIFT); - } break; - case OP_MOD: { - printf(" sar rax, %d\n", FIXNUM_SHIFT); - printf(" sar rcx, %d\n", FIXNUM_SHIFT); - printf(" mov rdx, 0\n"); - printf(" div rcx\n"); - printf(" mov rax, rdx\n"); - printf(" sal rax, %d\n", FIXNUM_SHIFT); - } break; - default: break; - } - printf(" push rax\n"); - printf(" ;; <-- arithmetic_op\n"); -} - -typedef void (CompileProc)(OpType, Object*); - void compile_type_predicate(OpType op, Object* args) { printf(" ;; --> compile_type_predicate\n"); @@ -143,19 +116,69 @@ compile_type_predicate(OpType op, Object* args) { // TODO: Next -> numerical comparison operators =, <=, ... // "=", "<", ">", "<=", ">=", // "not", "and", "or", -// NOTE: Make sure to stop evaluating if the condition is not met. + +void +compile_logic_list(OpType op, Object* args) { + printf(" ;; --> compile_logic_list\n"); + compile_object(args->head); + do { + // TODO: Make sure to stop evaluating if the condition is not met. + args = args->tail; + printf(" pop rax\n"); + switch (op) { + case OP_NOT: { + printf(" cmp rax, %d\n", FALSE_VAL); + printf(" mov rax, 0\n"); + } break; + default: break; + } + printf(" sete al\n"); + printf(" sal rax, %d\n", BOOL_SHIFT); + printf(" or rax, %d\n", BOOL_TAG); + printf(" push rax\n"); + } while (args != NULL); + printf(" ;; <-- compile_logic_list\n"); +} void compile_arithmetic_list(OpType op, Object* args) { - printf(" ;; --> compile_arithmetic_list\n"); + printf(" ;; --> compile_arithmetic\n"); compile_object(args->head); args = args->tail; while (args != NULL) { compile_object(args->head); args = args->tail; - arithmetic_op(op); + printf(" pop rcx\n"); + printf(" pop rax\n"); + switch (op) { + case OP_ADD: { printf(" add rax, rcx\n"); } break; + case OP_SUB: { printf(" sub rax, rcx\n"); } break; + case OP_MUL: { + printf(" sar rax, %d\n", FIXNUM_SHIFT); + printf(" sar rcx, %d\n", FIXNUM_SHIFT); + printf(" mul rcx\n"); + printf(" sal rax, %d\n", FIXNUM_SHIFT); + } break; + case OP_DIV: { + printf(" sar rax, %d\n", FIXNUM_SHIFT); + printf(" sar rcx, %d\n", FIXNUM_SHIFT); + printf(" mov rdx, 0\n"); + printf(" div rcx\n"); + printf(" sal rax, %d\n", FIXNUM_SHIFT); + } break; + case OP_MOD: { + printf(" sar rax, %d\n", FIXNUM_SHIFT); + printf(" sar rcx, %d\n", FIXNUM_SHIFT); + printf(" mov rdx, 0\n"); + printf(" div rcx\n"); + printf(" mov rax, rdx\n"); + printf(" sal rax, %d\n", FIXNUM_SHIFT); + } break; + default: break; + } + printf(" push rax\n"); } - printf(" ;; <-- compile_arithmetic_list\n"); + printf(" ;; <-- compile_arithmetic\n"); } void @@ -164,35 +187,45 @@ compile_proc_call(Object *obj) { // initialized at the start of the compilation procedure. if (sv_equal(&obj->head->text, &STRING("+"))) { compile_arithmetic_list(OP_ADD, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("-"))) { + } else if (sv_equal(&obj->head->text, &STRING("-"))) { compile_arithmetic_list(OP_SUB, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("*"))) { + } else if (sv_equal(&obj->head->text, &STRING("*"))) { compile_arithmetic_list(OP_MUL, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("/"))) { + } else if (sv_equal(&obj->head->text, &STRING("/"))) { compile_arithmetic_list(OP_DIV, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("%"))) { + } else if (sv_equal(&obj->head->text, &STRING("%"))) { compile_arithmetic_list(OP_MOD, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("nil?"))) { + } else if (sv_equal(&obj->head->text, &STRING("nil?"))) { compile_type_predicate(OP_IS_NIL, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("zero?"))) { + } else if (sv_equal(&obj->head->text, &STRING("zero?"))) { compile_type_predicate(OP_IS_ZERO, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("fixnum?"))) { + } else if (sv_equal(&obj->head->text, &STRING("fixnum?"))) { compile_type_predicate(OP_IS_FIXNUM, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("bool?"))) { + } else if (sv_equal(&obj->head->text, &STRING("bool?"))) { compile_type_predicate(OP_IS_BOOL, obj->tail); - } - if (sv_equal(&obj->head->text, &STRING("display"))) { + } else if (sv_equal(&obj->head->text, &STRING("display"))) { compile_object(obj->tail->head); printf(" pop rdi\n"); printf(" call display\n"); + } else if (sv_equal(&obj->head->text, &STRING("not"))) { + compile_logic_list(OP_NOT, obj->tail); + } else if (sv_equal(&obj->head->text, &STRING("and"))) { + compile_logic_list(OP_AND, obj->tail); + } else if (sv_equal(&obj->head->text, &STRING("or"))) { + compile_logic_list(OP_OR, obj->tail); + } else if (sv_equal(&obj->head->text, &STRING("="))) { + compile_logic_list(OP_EQUAL, obj->tail); + } else if (sv_equal(&obj->head->text, &STRING(">"))) { + compile_logic_list(OP_GREATER, obj->tail); + } else if (sv_equal(&obj->head->text, &STRING("<"))) { + compile_logic_list(OP_LESS, obj->tail); + } else if (sv_equal(&obj->head->text, &STRING(">="))) { + compile_logic_list(OP_GREATER_EQ, obj->tail); + } else if (sv_equal(&obj->head->text, &STRING("<="))) { + compile_logic_list(OP_LESS_EQL, obj->tail); + } else { + fprintf(stderr, "error: not implemented\n"); + exit(EXIT_FAILURE); } } -- cgit v1.2.1