From 58ffe8a7dbf57d5637e091083175028eb9614636 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 2 Nov 2021 16:55:17 +0100 Subject: Add numerical comparison operations (binary only) --- src/compiler.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 10 deletions(-) diff --git a/src/compiler.h b/src/compiler.h index a40fb1e..b703a99 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -79,7 +79,7 @@ typedef enum OpType { OP_GREATER, OP_LESS, OP_GREATER_EQ, - OP_LESS_EQL, + OP_LESS_EQ, } OpType; void @@ -112,10 +112,6 @@ compile_type_predicate(OpType op, Object* args) { printf(" ;; <-- compile_type_predicate\n"); } - -// TODO: Next -> numerical comparison operators -// "=", "<", ">", "<=", ">=", - void compile_logic_list(OpType op, Object* args) { printf(" ;; --> compile_logic_list\n"); @@ -162,6 +158,58 @@ compile_logic_list(OpType op, Object* args) { printf(" ;; <-- compile_logic_list\n"); } +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). + args = args->tail; + while (args != NULL) { + compile_object(args->head); + args = args->tail; + + // 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); + + 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; + default: break; + } + printf(" shl rax, %d\n", BOOL_SHIFT); + printf(" or rax, %d\n", BOOL_TAG); + printf(" push rax\n"); + } + printf(" ;; <-- compile_cmp_list\n"); +} + void compile_arithmetic_list(OpType op, Object* args) { printf(" ;; --> compile_arithmetic\n"); @@ -236,15 +284,15 @@ compile_proc_call(Object *obj) { } 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); + compile_cmp_list(OP_EQUAL, obj->tail); } else if (sv_equal(&obj->head->text, &STRING(">"))) { - compile_logic_list(OP_GREATER, obj->tail); + compile_cmp_list(OP_GREATER, obj->tail); } else if (sv_equal(&obj->head->text, &STRING("<"))) { - compile_logic_list(OP_LESS, obj->tail); + compile_cmp_list(OP_LESS, obj->tail); } else if (sv_equal(&obj->head->text, &STRING(">="))) { - compile_logic_list(OP_GREATER_EQ, obj->tail); + compile_cmp_list(OP_GREATER_EQ, obj->tail); } else if (sv_equal(&obj->head->text, &STRING("<="))) { - compile_logic_list(OP_LESS_EQL, obj->tail); + compile_cmp_list(OP_LESS_EQ, obj->tail); } else { fprintf(stderr, "error: not implemented\n"); exit(EXIT_FAILURE); -- cgit v1.2.1