From 9323c1285a8a9f7ec33e88d26f102d92c7a6e2ec Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 10 Oct 2021 14:15:45 +0200 Subject: Add cond special form --- examples/booleans.bdl | 21 +++++++++++++++++++++ src/bootstrap/main.c | 2 ++ src/bootstrap/primitives.c | 26 +++++++++++++++++++++++++- tests/booleans_expected.txt | 5 +++++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/examples/booleans.bdl b/examples/booleans.bdl index d526f25..24d57a0 100644 --- a/examples/booleans.bdl +++ b/examples/booleans.bdl @@ -54,3 +54,24 @@ (print "(if (or (+ 1 2 3) false) (+ 1 2 3) (+ 7 8 9)) -> ") (if (or (+ 1 2 3) false) (+ 1 2 3) (+ 7 8 9)) (print "(if true 7) -> ") (if true 7) (print "(if false 7) -> ") (if false 7) + +;; Cond. +(print "(cond ((and true true true) 1) ((or true true false) 2) (else 3)) -> ") +(cond ((and true true true) 1) + ((or true true false) 2) + (else 3)) +(print "(cond ((and true true false) 1) ((or true true false) 2) (else 3)) -> ") +(cond ((and true true false) 1) + ((or true true false) 2) + (else 3)) +(print "(cond ((and true true false) 1) ((or false false false) 2) (else 3)) -> ") +(cond ((and true true false) 1) + ((or false false false) 2) + (else 3)) +(print "(cond ((and true true true) 1) ((or true true false) 2)) -> ") +(cond ((and true true false) 1) + ((or false false false) 2)) +(print "(cond ((and true true true) (+ 1 2 3)) ((or true true false) 2) (else 3)) -> ") +(cond ((and true true true) (+ 1 2 3)) + ((or true true false) 2) + (else 3)) diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index 8ec1231..c0f2e50 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c @@ -41,6 +41,8 @@ init(void) { environment[env_n++] = (EnvSymbol){MAKE_SYM("and"), make_procedure(proc_and)}; environment[env_n++] = (EnvSymbol){MAKE_SYM("or"), make_procedure(proc_or)}; environment[env_n++] = (EnvSymbol){MAKE_SYM("if"), make_procedure(proc_if)}; + environment[env_n++] = (EnvSymbol){MAKE_SYM("else"), obj_true}; + environment[env_n++] = (EnvSymbol){MAKE_SYM("cond"), make_procedure(proc_cond)}; environment[env_n++] = (EnvSymbol){MAKE_SYM("display"), make_procedure(proc_display)}; environment[env_n++] = (EnvSymbol){MAKE_SYM("print"), make_procedure(proc_print)}; } diff --git a/src/bootstrap/primitives.c b/src/bootstrap/primitives.c index 61ce360..29a1df8 100644 --- a/src/bootstrap/primitives.c +++ b/src/bootstrap/primitives.c @@ -329,6 +329,30 @@ proc_if(Object *args) { return obj_nil; } -// TODO: cond +Object * +proc_cond(Object *args) { + if (args->type != OBJ_TYPE_PAIR) { + fprintf(stderr, "error: wrong number of arguments.\n"); + return NULL; + } + + if (args->car->type != OBJ_TYPE_PAIR) { + fprintf(stderr, "error: wrong argument type.\n"); + return NULL; + } + + while (args != obj_nil) { + Object *clause = args->car; + if (eval(clause->car) == obj_true) { + return eval(clause->cdr->car); + } + + args = args->cdr; + clause = args->car; + } + + return obj_nil; +} + // TODO: equality greater than smaller than... // TODO: fixnum left/right shift, mask, invert diff --git a/tests/booleans_expected.txt b/tests/booleans_expected.txt index d05d314..f0612b8 100644 --- a/tests/booleans_expected.txt +++ b/tests/booleans_expected.txt @@ -41,3 +41,8 @@ (if (or (+ 1 2 3) false) (+ 1 2 3) (+ 7 8 9)) -> 6 (if true 7) -> 7 (if false 7) -> () +(cond ((and true true true) 1) ((or true true false) 2) (else 3)) -> 1 +(cond ((and true true false) 1) ((or true true false) 2) (else 3)) -> 2 +(cond ((and true true false) 1) ((or false false false) 2) (else 3)) -> 3 +(cond ((and true true true) 1) ((or true true false) 2)) -> () +(cond ((and true true true) (+ 1 2 3)) ((or true true false) 2) (else 3)) -> 6 -- cgit v1.2.1