From 889e34d0ca986f03de77dfa383c12f4980e746ee Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Wed, 3 Nov 2021 14:51:42 +0100 Subject: Fix behaviour of logic comparisons --- src/compiler.h | 96 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/src/compiler.h b/src/compiler.h index 441b665..e511b7c 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -26,10 +26,11 @@ generate_label(void) { // for freeing the memory. static size_t label_counter = 0; char buf[32]; - memset(buf, 0, 32); sprintf(buf, ".BDLL%ld", label_counter++); - char * ret = malloc(strlen(buf)); - memcpy(ret, buf, strlen(buf)); + size_t len = strlen(buf); + char * ret = malloc(len + 1); + memcpy(ret, buf, len); + ret[len] = 0; return ret; } @@ -85,9 +86,6 @@ typedef enum OpType { OP_IS_BOOL, OP_IS_FIXNUM, // Logic operations. - OP_NOT, - OP_AND, - OP_OR, OP_EQUAL, OP_GREATER, OP_LESS, @@ -126,49 +124,65 @@ compile_type_predicate(OpType op, Object* args) { } void -compile_logic_list(OpType op, Object* args) { - printf(" ;; --> compile_logic_list\n"); +compile_not(Object* args) { + printf(" ;; --> compile_not\n"); compile_object(args->head); - if (op == OP_NOT) { + printf(" pop rax\n"); + printf(" cmp rax, %d\n", FALSE_VAL); + printf(" mov rax, 0\n"); + printf(" sete al\n"); + printf(" shl rax, %d\n", BOOL_SHIFT); + printf(" or rax, %d\n", BOOL_TAG); + printf(" push rax\n"); + printf(" ;; <-- compile_not\n"); +} + +void +compile_and(Object *args) { + printf(" ;; --> compile_and\n"); + char *lab_false = generate_label(); + char *lab_exit = generate_label(); + while (args != NULL) { + compile_object(args->head); + args = args->tail; printf(" pop rax\n"); printf(" cmp rax, %d\n", FALSE_VAL); - printf(" mov rax, 0\n"); - printf(" sete al\n"); - printf(" shl rax, %d\n", BOOL_SHIFT); - printf(" or rax, %d\n", BOOL_TAG); - printf(" push rax\n"); - printf(" ;; <-- compile_logic_list\n"); - return; + printf(" je %s\n", lab_false); } + printf(" mov rax, %d\n", TRUE_VAL); + printf(" push rax\n"); + printf(" jmp %s\n", lab_exit); + printf("%s:\n", lab_false); + printf(" mov rax, %d\n", FALSE_VAL); + printf(" push rax\n"); + printf("%s:\n", lab_exit); + free(lab_false); + free(lab_exit); + printf(" ;; <-- compile_and\n"); +} - // TODO: Make sure to stop evaluating if the condition is not met. - args = args->tail; +void +compile_or(Object *args) { + printf(" ;; --> compile_or\n"); + char *lab_true = generate_label(); + char *lab_exit = generate_label(); while (args != NULL) { compile_object(args->head); args = args->tail; - - // Current value. - printf(" pop rcx\n"); - printf(" cmp rcx, %d\n", FALSE_VAL); - printf(" mov rcx, 0\n"); - printf(" setne cl\n"); - - // Previous value. printf(" pop rax\n"); printf(" cmp rax, %d\n", FALSE_VAL); - printf(" mov rax, 0\n"); - printf(" setne al\n"); - - switch (op) { - case OP_AND: { printf(" and al, cl\n"); } break; - case OP_OR: { printf(" or al, cl\n"); } break; - default: break; - } - printf(" shl rax, %d\n", BOOL_SHIFT); - printf(" or rax, %d\n", BOOL_TAG); - printf(" push rax\n"); + printf(" jne %s\n", lab_true); } - printf(" ;; <-- compile_logic_list\n"); + printf(" mov rax, %d\n", FALSE_VAL); + printf(" push rax\n"); + printf(" jmp %s\n", lab_exit); + printf("%s:\n", lab_true); + printf(" mov rax, %d\n", TRUE_VAL); + printf(" push rax\n"); + printf("%s:\n", lab_exit); + free(lab_true); + free(lab_exit); + printf(" ;; <-- compile_or\n"); } void @@ -291,11 +305,11 @@ compile_proc_call(Object *obj) { printf(" pop rdi\n"); printf(" call display\n"); } else if (sv_equal(&obj->head->text, &STRING("not"))) { - compile_logic_list(OP_NOT, obj->tail); + compile_not(obj->tail); } else if (sv_equal(&obj->head->text, &STRING("and"))) { - compile_logic_list(OP_AND, obj->tail); + compile_and(obj->tail); } else if (sv_equal(&obj->head->text, &STRING("or"))) { - compile_logic_list(OP_OR, obj->tail); + compile_or(obj->tail); } else if (sv_equal(&obj->head->text, &STRING("="))) { compile_cmp_list(OP_EQUAL, obj->tail); } else if (sv_equal(&obj->head->text, &STRING(">"))) { -- cgit v1.2.1