From 9c8022b286993ea4123211005878681bd207fa0c Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Wed, 3 Nov 2021 15:08:48 +0100 Subject: Fix behaviour of numerical comparisons --- src/compiler.h | 48 +++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/compiler.h b/src/compiler.h index e511b7c..ff2c6e0 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -189,13 +189,8 @@ void compile_cmp_list(OpType op, Object* args) { printf(" ;; --> compile_cmp_list\n"); compile_object(args->head); - - // TODO: Make sure to stop evaluating if the condition is not met. - // FIXME: Only working for two argument lists right now because we can't - // accumulate the bool and compare it with an int. We can fix it by passing - // two values on the stack (previous value and current result) or by only - // passing a previous value and having a conditional jump (need labels for - // that). + char *lab_false = generate_label(); + char *lab_exit = generate_label(); args = args->tail; while (args != NULL) { compile_object(args->head); @@ -203,37 +198,32 @@ compile_cmp_list(OpType op, Object* args) { // Current value. printf(" pop rcx\n"); - printf(" sar rcx, %d\n", FIXNUM_SHIFT); // Previous value. printf(" pop rax\n"); - printf(" sar rax, %d\n", FIXNUM_SHIFT); + // Comparison. printf(" cmp rax, rcx\n"); - printf(" mov rax, 0\n"); - switch (op) { - case OP_EQUAL: { - printf(" sete al\n"); - } break; - case OP_GREATER: { - printf(" setg al\n"); - } break; - case OP_LESS: { - printf(" setl al\n"); - } break; - case OP_GREATER_EQ: { - printf(" setge al\n"); - } break; - case OP_LESS_EQ: { - printf(" setle al\n"); - } break; + case OP_EQUAL: { printf(" jne %s\n", lab_false); } break; + case OP_GREATER: { printf(" jle %s\n", lab_false); } break; + case OP_LESS: { printf(" jge %s\n", lab_false); } break; + case OP_GREATER_EQ: { printf(" jl %s\n", lab_false); } break; + case OP_LESS_EQ: { printf(" jg %s\n", lab_false); } break; default: break; } - printf(" shl rax, %d\n", BOOL_SHIFT); - printf(" or rax, %d\n", BOOL_TAG); - printf(" push rax\n"); + printf(" push rcx\n"); } + printf(" pop rcx\n"); + 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_cmp_list\n"); } -- cgit v1.2.1