diff options
author | Bad Diode <bd@badd10de.dev> | 2021-10-10 12:11:45 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-10-10 12:11:45 +0200 |
commit | 4673fde605090320fbab227e56bb085eec97362a (patch) | |
tree | 5d510484d5543b4b11fd62b42a4b1e14672ff2cd /src | |
parent | c2bfb5368e603d686190fdc9f3ddbafbda075a9c (diff) | |
download | bdl-4673fde605090320fbab227e56bb085eec97362a.tar.gz bdl-4673fde605090320fbab227e56bb085eec97362a.zip |
Add boolean primitives and more (better) tests
Diffstat (limited to 'src')
-rw-r--r-- | src/bootstrap/lexer.c | 2 | ||||
-rwxr-xr-x | src/bootstrap/main.c | 10 | ||||
-rw-r--r-- | src/bootstrap/primitives.c | 95 | ||||
-rw-r--r-- | src/bootstrap/readline.c | 2 | ||||
-rw-r--r-- | src/bootstrap/string_view.c | 18 |
5 files changed, 113 insertions, 14 deletions
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 | |||
51 | tokenize(StringView sv) { | 51 | tokenize(StringView sv) { |
52 | // NOTE: Not allocating any memory for now, but we are limited by a maximum | 52 | // NOTE: Not allocating any memory for now, but we are limited by a maximum |
53 | // number of tokens we can process. | 53 | // number of tokens we can process. |
54 | #define TOKENS_BUF_SIZE 1024 | 54 | #define TOKENS_BUF_SIZE KB(64) |
55 | static Token tokens_buf[TOKENS_BUF_SIZE]; | 55 | static Token tokens_buf[TOKENS_BUF_SIZE]; |
56 | 56 | ||
57 | // Clear buffer. | 57 | // 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) { | |||
37 | environment[env_n++] = (EnvSymbol){MAKE_SYM("*"), make_procedure(proc_mul)}; | 37 | environment[env_n++] = (EnvSymbol){MAKE_SYM("*"), make_procedure(proc_mul)}; |
38 | environment[env_n++] = (EnvSymbol){MAKE_SYM("/"), make_procedure(proc_div)}; | 38 | environment[env_n++] = (EnvSymbol){MAKE_SYM("/"), make_procedure(proc_div)}; |
39 | environment[env_n++] = (EnvSymbol){MAKE_SYM("boolean?"), make_procedure(proc_is_boolean)}; | 39 | environment[env_n++] = (EnvSymbol){MAKE_SYM("boolean?"), make_procedure(proc_is_boolean)}; |
40 | environment[env_n++] = (EnvSymbol){MAKE_SYM("false?"), make_procedure(proc_is_false)}; | 40 | environment[env_n++] = (EnvSymbol){MAKE_SYM("not"), make_procedure(proc_not)}; |
41 | environment[env_n++] = (EnvSymbol){MAKE_SYM("and"), make_procedure(proc_and)}; | ||
42 | environment[env_n++] = (EnvSymbol){MAKE_SYM("or"), make_procedure(proc_or)}; | ||
41 | environment[env_n++] = (EnvSymbol){MAKE_SYM("display"), make_procedure(proc_display)}; | 43 | environment[env_n++] = (EnvSymbol){MAKE_SYM("display"), make_procedure(proc_display)}; |
44 | environment[env_n++] = (EnvSymbol){MAKE_SYM("print"), make_procedure(proc_print)}; | ||
42 | } | 45 | } |
43 | 46 | ||
44 | void | 47 | void |
@@ -64,8 +67,9 @@ eval_line(FILE *fd, char delimiter) { | |||
64 | printf("\n"); | 67 | printf("\n"); |
65 | printf("EVAL: "); | 68 | printf("EVAL: "); |
66 | #endif | 69 | #endif |
67 | display(eval(ast)); | 70 | if (display(eval(ast))) { |
68 | printf("\n"); | 71 | printf("\n"); |
72 | }; | ||
69 | } | 73 | } |
70 | } | 74 | } |
71 | } | 75 | } |
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 @@ | |||
1 | void display(Object *root); | 1 | bool display(Object *root); |
2 | 2 | ||
3 | void | 3 | void |
4 | display_pair(Object *root) { | 4 | display_pair(Object *root) { |
@@ -6,7 +6,7 @@ display_pair(Object *root) { | |||
6 | if (root->cdr->type == OBJ_TYPE_PAIR) { | 6 | if (root->cdr->type == OBJ_TYPE_PAIR) { |
7 | printf(" "); | 7 | printf(" "); |
8 | display_pair(root->cdr); | 8 | display_pair(root->cdr); |
9 | } else if (root->cdr->type == OBJ_TYPE_NIL) { | 9 | } else if (root->cdr == obj_nil) { |
10 | return; | 10 | return; |
11 | } else { | 11 | } else { |
12 | printf(" . "); | 12 | printf(" . "); |
@@ -14,10 +14,10 @@ display_pair(Object *root) { | |||
14 | } | 14 | } |
15 | } | 15 | } |
16 | 16 | ||
17 | void | 17 | bool |
18 | display(Object *root) { | 18 | display(Object *root) { |
19 | if (root == NULL) { | 19 | if (root == NULL) { |
20 | return; | 20 | return false; |
21 | } | 21 | } |
22 | 22 | ||
23 | switch (root->type) { | 23 | switch (root->type) { |
@@ -49,6 +49,7 @@ display(Object *root) { | |||
49 | printf("#{procedure}"); | 49 | printf("#{procedure}"); |
50 | } break; | 50 | } break; |
51 | } | 51 | } |
52 | return true; | ||
52 | } | 53 | } |
53 | 54 | ||
54 | Object * | 55 | Object * |
@@ -223,14 +224,90 @@ proc_display(Object *args) { | |||
223 | } | 224 | } |
224 | 225 | ||
225 | Object * | 226 | Object * |
227 | proc_print(Object *args) { | ||
228 | if (args == NULL) { | ||
229 | return NULL; | ||
230 | } | ||
231 | if (args->type == OBJ_TYPE_PAIR) { | ||
232 | Object *obj = args->car; | ||
233 | if (obj->type == OBJ_TYPE_STRING) { | ||
234 | StringView scanner = (StringView) { | ||
235 | .start = obj->string, | ||
236 | .n = obj->string_n, | ||
237 | }; | ||
238 | while (scanner.n != 0) { | ||
239 | char c = sv_next(&scanner); | ||
240 | if (c == '\\' && sv_peek(&scanner) == 'n') { | ||
241 | putchar('\n'); | ||
242 | sv_next(&scanner); | ||
243 | continue; | ||
244 | } | ||
245 | if (c == '\\' && sv_peek(&scanner) == '"') { | ||
246 | putchar('"'); | ||
247 | sv_next(&scanner); | ||
248 | continue; | ||
249 | } | ||
250 | putchar(c); | ||
251 | } | ||
252 | } else { | ||
253 | fprintf(stderr, "error: print requires a string argument\n"); | ||
254 | } | ||
255 | } | ||
256 | return NULL; | ||
257 | } | ||
258 | |||
259 | Object * | ||
226 | proc_is_boolean(Object *args) { | 260 | proc_is_boolean(Object *args) { |
227 | if (args->car == obj_true || args->car == obj_false) { | 261 | Object *obj = NULL; |
228 | return obj_true; | 262 | if (args->type == OBJ_TYPE_PAIR) { |
263 | obj = eval(args->car); | ||
264 | } else { | ||
265 | obj = eval(args); | ||
229 | } | 266 | } |
230 | return obj_false; | 267 | return (obj == obj_true || obj == obj_false) ? obj_true : obj_false; |
268 | } | ||
269 | |||
270 | Object * | ||
271 | proc_not(Object *args) { | ||
272 | if (args->type == OBJ_TYPE_PAIR) { | ||
273 | return eval(args->car) == obj_false ? obj_true : obj_false; | ||
274 | } | ||
275 | return eval(args) == obj_false ? obj_true : obj_false; | ||
276 | } | ||
277 | |||
278 | Object * | ||
279 | proc_and(Object *args) { | ||
280 | while (args != NULL && args != obj_nil) { | ||
281 | Object *obj = args->car; | ||
282 | if (args->car->type == OBJ_TYPE_PAIR) { | ||
283 | obj = eval(args->car); | ||
284 | } | ||
285 | if (proc_not(obj) == obj_true) { | ||
286 | return obj_false; | ||
287 | } | ||
288 | args = args->cdr; | ||
289 | } | ||
290 | return obj_true; | ||
231 | } | 291 | } |
232 | 292 | ||
233 | Object * | 293 | Object * |
234 | proc_is_false(Object *args) { | 294 | proc_or(Object *args) { |
235 | return args->car == obj_false ? obj_true : obj_false; | 295 | if (args->type != OBJ_TYPE_PAIR) { |
296 | return obj_false; | ||
297 | } | ||
298 | |||
299 | while (args != NULL && args != obj_nil) { | ||
300 | Object *obj = args->car; | ||
301 | if (args->car->type == OBJ_TYPE_PAIR) { | ||
302 | obj = eval(args->car); | ||
303 | } | ||
304 | if (proc_not(obj) == obj_false) { | ||
305 | return obj_true; | ||
306 | } | ||
307 | args = args->cdr; | ||
308 | } | ||
309 | return obj_false; | ||
236 | } | 310 | } |
311 | |||
312 | // TODO: if/cond | ||
313 | // 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 @@ | |||
2 | 2 | ||
3 | StringView | 3 | StringView |
4 | read_line(FILE *fd, char delimiter) { | 4 | read_line(FILE *fd, char delimiter) { |
5 | #define RL_BUF_SIZE 1024 | 5 | #define RL_BUF_SIZE KB(64) |
6 | static char readline_buf[RL_BUF_SIZE]; | 6 | static char readline_buf[RL_BUF_SIZE]; |
7 | 7 | ||
8 | // Clear buffer. | 8 | // 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) { | |||
23 | return false; | 23 | return false; |
24 | } | 24 | } |
25 | 25 | ||
26 | char | ||
27 | sv_next(StringView *sv) { | ||
28 | if (sv->n == 0) { | ||
29 | return '\0'; | ||
30 | } | ||
31 | char ret = sv->start[0]; | ||
32 | sv->start++; | ||
33 | sv->n--; | ||
34 | return ret; | ||
35 | } | ||
36 | |||
37 | char | ||
38 | sv_peek(const StringView *sv) { | ||
39 | if (sv->n == 0) { | ||
40 | return '\0'; | ||
41 | } | ||
42 | return sv->start[0]; | ||
43 | } | ||