aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-10 12:11:45 +0200
committerBad Diode <bd@badd10de.dev>2021-10-10 12:11:45 +0200
commit4673fde605090320fbab227e56bb085eec97362a (patch)
tree5d510484d5543b4b11fd62b42a4b1e14672ff2cd /src
parentc2bfb5368e603d686190fdc9f3ddbafbda075a9c (diff)
downloadbdl-4673fde605090320fbab227e56bb085eec97362a.tar.gz
bdl-4673fde605090320fbab227e56bb085eec97362a.zip
Add boolean primitives and more (better) tests
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/lexer.c2
-rwxr-xr-xsrc/bootstrap/main.c10
-rw-r--r--src/bootstrap/primitives.c95
-rw-r--r--src/bootstrap/readline.c2
-rw-r--r--src/bootstrap/string_view.c18
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
51tokenize(StringView sv) { 51tokenize(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
44void 47void
@@ -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 @@
1void display(Object *root); 1bool display(Object *root);
2 2
3void 3void
4display_pair(Object *root) { 4display_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
17void 17bool
18display(Object *root) { 18display(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
54Object * 55Object *
@@ -223,14 +224,90 @@ proc_display(Object *args) {
223} 224}
224 225
225Object * 226Object *
227proc_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
259Object *
226proc_is_boolean(Object *args) { 260proc_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
270Object *
271proc_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
278Object *
279proc_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
233Object * 293Object *
234proc_is_false(Object *args) { 294proc_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
3StringView 3StringView
4read_line(FILE *fd, char delimiter) { 4read_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
26char
27sv_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
37char
38sv_peek(const StringView *sv) {
39 if (sv->n == 0) {
40 return '\0';
41 }
42 return sv->start[0];
43}