From 9866fad84ada32ef4f386e8be6ca09bd3711f034 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Mon, 1 Nov 2021 17:58:57 +0100 Subject: Add type predicate primitive procedures Added: nil?, zero?, bool?, fixnum? --- src/compiler.h | 110 +++++++++++++++++++++++++++++++++++++++++++++------------ src/parser.c | 1 + 2 files changed, 88 insertions(+), 23 deletions(-) diff --git a/src/compiler.h b/src/compiler.h index 7d6fa6b..76d6ccf 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -58,11 +58,18 @@ compile_nil(void) { } typedef enum OpType { + // Arithmetic. OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, + // Type predicates. + OP_IS_NIL, + OP_IS_ZERO, + OP_IS_BOOL, + OP_IS_FIXNUM, + // TODO: etc. } OpType; void @@ -70,47 +77,71 @@ arithmetic_op(OpType type) { printf(" ;; --> arithmetic_op\n"); printf(" pop rcx\n"); printf(" pop rax\n"); - printf(" sar rax, %d\n", FIXNUM_SHIFT); - printf(" sar rcx, %d\n", FIXNUM_SHIFT); switch (type) { - case OP_ADD: { - printf(" add rax, rcx\n"); - } break; - case OP_SUB: { - printf(" sub rax, rcx\n"); - } break; + 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; } - // No need to add the FIXNUM_TAG here, since it's zero. - printf(" sal rax, %d\n", FIXNUM_SHIFT); printf(" push rax\n"); printf(" ;; <-- arithmetic_op\n"); } +typedef void (CompileProc)(OpType, Object*); + 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_type_predicate(OpType op, Object* args) { + printf(" ;; --> compile_type_predicate\n"); + compile_object(args->head); + printf(" pop rax\n"); + switch (op) { + case OP_IS_NIL: { + printf(" cmp rax, %d\n", NIL_VAL); + } break; + case OP_IS_ZERO: { + printf(" cmp rax, 0\n"); + } break; + case OP_IS_BOOL: { + printf(" and rax, %d\n", BOOL_MASK); + printf(" cmp rax, %d\n", BOOL_TAG); + } break; + case OP_IS_FIXNUM: { + printf(" and rax, %d\n", FIXNUM_MASK); + printf(" cmp rax, %d\n", FIXNUM_TAG); + } break; + default: break; + } + printf(" mov rax, 0\n"); + printf(" sete al\n"); + printf(" sal rax, %d\n", BOOL_SHIFT); + printf(" or rax, %d\n", BOOL_TAG); + printf(" push rax\n"); + printf(" ;; <-- compile_type_predicate\n"); +} + +void +compile_arithmetic_list(OpType op, Object* args) { + printf(" ;; --> compile_arithmetic_list\n"); compile_object(args->head); args = args->tail; while (args != NULL) { @@ -118,7 +149,40 @@ compile_proc_call(Object *obj) { args = args->tail; arithmetic_op(op); } - printf(" ;; <-- compile_proc_call\n"); + printf(" ;; <-- compile_arithmetic_list\n"); +} + +void +compile_proc_call(Object *obj) { + // TODO: Probably we want to use a hash table for these lookups that is + // 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("-"))) { + compile_arithmetic_list(OP_SUB, obj->tail); + } + if (sv_equal(&obj->head->text, &STRING("*"))) { + compile_arithmetic_list(OP_MUL, obj->tail); + } + if (sv_equal(&obj->head->text, &STRING("/"))) { + compile_arithmetic_list(OP_DIV, obj->tail); + } + if (sv_equal(&obj->head->text, &STRING("%"))) { + compile_arithmetic_list(OP_MOD, obj->tail); + } + if (sv_equal(&obj->head->text, &STRING("nil?"))) { + compile_type_predicate(OP_IS_NIL, obj->tail); + } + if (sv_equal(&obj->head->text, &STRING("zero?"))) { + compile_type_predicate(OP_IS_ZERO, obj->tail); + } + if (sv_equal(&obj->head->text, &STRING("fixnum?"))) { + compile_type_predicate(OP_IS_FIXNUM, obj->tail); + } + if (sv_equal(&obj->head->text, &STRING("bool?"))) { + compile_type_predicate(OP_IS_BOOL, obj->tail); + } } void diff --git a/src/parser.c b/src/parser.c index 57efd96..86cf713 100644 --- a/src/parser.c +++ b/src/parser.c @@ -9,6 +9,7 @@ static char *builtins [] = { "+", "-", "*", "/", "%", "=", "<", ">", "<=", ">=", "not", "and", "or", + "nil?", "zero?", "fixnum?", "bool?", }; uint64_t -- cgit v1.2.1