From 4673fde605090320fbab227e56bb085eec97362a Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 10 Oct 2021 12:11:45 +0200 Subject: Add boolean primitives and more (better) tests --- src/bootstrap/primitives.c | 95 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 9 deletions(-) (limited to 'src/bootstrap/primitives.c') diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c index e4c18cd..97058f9 100644 --- a/src/bootstrap/primitives.c +++ b/src/bootstrap/primitives.c @@ -1,4 +1,4 @@ -void display(Object *root); +bool display(Object *root); void display_pair(Object *root) { @@ -6,7 +6,7 @@ display_pair(Object *root) { if (root->cdr->type == OBJ_TYPE_PAIR) { printf(" "); display_pair(root->cdr); - } else if (root->cdr->type == OBJ_TYPE_NIL) { + } else if (root->cdr == obj_nil) { return; } else { printf(" . "); @@ -14,10 +14,10 @@ display_pair(Object *root) { } } -void +bool display(Object *root) { if (root == NULL) { - return; + return false; } switch (root->type) { @@ -49,6 +49,7 @@ display(Object *root) { printf("#{procedure}"); } break; } + return true; } Object * @@ -222,15 +223,91 @@ proc_display(Object *args) { return obj_nil; } +Object * +proc_print(Object *args) { + if (args == NULL) { + return NULL; + } + if (args->type == OBJ_TYPE_PAIR) { + Object *obj = args->car; + if (obj->type == OBJ_TYPE_STRING) { + StringView scanner = (StringView) { + .start = obj->string, + .n = obj->string_n, + }; + while (scanner.n != 0) { + char c = sv_next(&scanner); + if (c == '\\' && sv_peek(&scanner) == 'n') { + putchar('\n'); + sv_next(&scanner); + continue; + } + if (c == '\\' && sv_peek(&scanner) == '"') { + putchar('"'); + sv_next(&scanner); + continue; + } + putchar(c); + } + } else { + fprintf(stderr, "error: print requires a string argument\n"); + } + } + return NULL; +} + Object * proc_is_boolean(Object *args) { - if (args->car == obj_true || args->car == obj_false) { - return obj_true; + Object *obj = NULL; + if (args->type == OBJ_TYPE_PAIR) { + obj = eval(args->car); + } else { + obj = eval(args); } - return obj_false; + return (obj == obj_true || obj == obj_false) ? obj_true : obj_false; +} + +Object * +proc_not(Object *args) { + if (args->type == OBJ_TYPE_PAIR) { + return eval(args->car) == obj_false ? obj_true : obj_false; + } + return eval(args) == obj_false ? obj_true : obj_false; +} + +Object * +proc_and(Object *args) { + while (args != NULL && args != obj_nil) { + Object *obj = args->car; + if (args->car->type == OBJ_TYPE_PAIR) { + obj = eval(args->car); + } + if (proc_not(obj) == obj_true) { + return obj_false; + } + args = args->cdr; + } + return obj_true; } Object * -proc_is_false(Object *args) { - return args->car == obj_false ? obj_true : obj_false; +proc_or(Object *args) { + if (args->type != OBJ_TYPE_PAIR) { + return obj_false; + } + + while (args != NULL && args != obj_nil) { + Object *obj = args->car; + if (args->car->type == OBJ_TYPE_PAIR) { + obj = eval(args->car); + } + if (proc_not(obj) == obj_false) { + return obj_true; + } + args = args->cdr; + } + return obj_false; } + +// TODO: if/cond +// TODO: fixnum left/right shift, mask, invert -- cgit v1.2.1