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/lexer.c | 2 +- src/bootstrap/main.c | 10 +++-- src/bootstrap/primitives.c | 95 ++++++++++++++++++++++++++++++++++++++++----- src/bootstrap/readline.c | 2 +- src/bootstrap/string_view.c | 18 +++++++++ 5 files changed, 113 insertions(+), 14 deletions(-) (limited to 'src/bootstrap') diff --git a/src/bootstrap/lexer.c b/src/bootstrap/lexer.c index dd5c0f2..b03db77 100644 --- a/src/bootstrap/lexer.c +++ b/src/bootstrap/lexer.c @@ -51,7 +51,7 @@ Tokens tokenize(StringView sv) { // NOTE: Not allocating any memory for now, but we are limited by a maximum // number of tokens we can process. - #define TOKENS_BUF_SIZE 1024 + #define TOKENS_BUF_SIZE KB(64) static Token tokens_buf[TOKENS_BUF_SIZE]; // Clear buffer. diff --git a/src/bootstrap/main.c b/src/bootstrap/main.c index 95b2e49..a8ba7bc 100755 --- a/src/bootstrap/main.c +++ b/src/bootstrap/main.c @@ -37,8 +37,11 @@ init(void) { environment[env_n++] = (EnvSymbol){MAKE_SYM("*"), make_procedure(proc_mul)}; environment[env_n++] = (EnvSymbol){MAKE_SYM("/"), make_procedure(proc_div)}; environment[env_n++] = (EnvSymbol){MAKE_SYM("boolean?"), make_procedure(proc_is_boolean)}; - environment[env_n++] = (EnvSymbol){MAKE_SYM("false?"), make_procedure(proc_is_false)}; + environment[env_n++] = (EnvSymbol){MAKE_SYM("not"), make_procedure(proc_not)}; + 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("display"), make_procedure(proc_display)}; + environment[env_n++] = (EnvSymbol){MAKE_SYM("print"), make_procedure(proc_print)}; } void @@ -64,8 +67,9 @@ eval_line(FILE *fd, char delimiter) { printf("\n"); printf("EVAL: "); #endif - display(eval(ast)); - printf("\n"); + if (display(eval(ast))) { + printf("\n"); + }; } } } 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 diff --git a/src/bootstrap/readline.c b/src/bootstrap/readline.c index dfd8285..ae03e4a 100644 --- a/src/bootstrap/readline.c +++ b/src/bootstrap/readline.c @@ -2,7 +2,7 @@ StringView read_line(FILE *fd, char delimiter) { - #define RL_BUF_SIZE 1024 + #define RL_BUF_SIZE KB(64) static char readline_buf[RL_BUF_SIZE]; // Clear buffer. diff --git a/src/bootstrap/string_view.c b/src/bootstrap/string_view.c index 3cf275a..e958a46 100644 --- a/src/bootstrap/string_view.c +++ b/src/bootstrap/string_view.c @@ -23,3 +23,21 @@ sv_equal(StringView a, StringView b) { return false; } +char +sv_next(StringView *sv) { + if (sv->n == 0) { + return '\0'; + } + char ret = sv->start[0]; + sv->start++; + sv->n--; + return ret; +} + +char +sv_peek(const StringView *sv) { + if (sv->n == 0) { + return '\0'; + } + return sv->start[0]; +} -- cgit v1.2.1