diff options
author | Bad Diode <bd@badd10de.dev> | 2021-11-04 11:58:53 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-11-04 11:58:53 +0100 |
commit | 7cbef14e8393475b1e569fdbfff2c46db859d43f (patch) | |
tree | c7a25a997fae700f5f7a952a9550d6ee74bea240 | |
parent | 84c2bf292ddcb91543715951805ebc2335c46567 (diff) | |
download | bdl-7cbef14e8393475b1e569fdbfff2c46db859d43f.tar.gz bdl-7cbef14e8393475b1e569fdbfff2c46db859d43f.zip |
Add `cons`, `car` and `cdr` primitives
-rw-r--r-- | src/compiler.h | 72 | ||||
-rw-r--r-- | src/parser.c | 1 | ||||
-rw-r--r-- | src/x86_64/postlude.asm | 4 | ||||
-rw-r--r-- | src/x86_64/prelude.asm | 7 |
4 files changed, 76 insertions, 8 deletions
diff --git a/src/compiler.h b/src/compiler.h index 7323f4d..070f24a 100644 --- a/src/compiler.h +++ b/src/compiler.h | |||
@@ -5,15 +5,24 @@ | |||
5 | #define PRELUDE_FILE "src/x86_64/prelude.asm" | 5 | #define PRELUDE_FILE "src/x86_64/prelude.asm" |
6 | #define POSTLUDE_FILE "src/x86_64/postlude.asm" | 6 | #define POSTLUDE_FILE "src/x86_64/postlude.asm" |
7 | 7 | ||
8 | #define NIL_VAL 1 | 8 | #define HEAP_SIZE MB(32) |
9 | #define BOOL_MASK 3 | 9 | |
10 | #define BOOL_TAG 3 | 10 | // Immediate constants. |
11 | #define BOOL_SHIFT 2 | 11 | #define NIL_VAL 47 |
12 | #define BOOL_MASK 127 | ||
13 | #define BOOL_TAG 31 | ||
14 | #define BOOL_SHIFT 7 | ||
12 | #define TRUE_VAL ((1 << BOOL_SHIFT) | BOOL_TAG) | 15 | #define TRUE_VAL ((1 << BOOL_SHIFT) | BOOL_TAG) |
13 | #define FALSE_VAL ((0 << BOOL_SHIFT) | BOOL_TAG) | 16 | #define FALSE_VAL ((0 << BOOL_SHIFT) | BOOL_TAG) |
14 | #define FIXNUM_MASK 1 | 17 | #define FIXNUM_MASK 3 |
15 | #define FIXNUM_TAG 0 | 18 | #define FIXNUM_TAG 0 |
16 | #define FIXNUM_SHIFT 1 | 19 | #define FIXNUM_SHIFT 2 |
20 | |||
21 | // Heap allocated objects. | ||
22 | #define STRING_MASK 7 | ||
23 | #define STRING_TAG 3 | ||
24 | #define PAIR_MASK 7 | ||
25 | #define PAIR_TAG 1 | ||
17 | 26 | ||
18 | void compile_object(Object *obj); | 27 | void compile_object(Object *obj); |
19 | void compile_fixnum(Object *obj); | 28 | void compile_fixnum(Object *obj); |
@@ -269,6 +278,49 @@ compile_arithmetic_list(OpType op, Object* args) { | |||
269 | } | 278 | } |
270 | 279 | ||
271 | void | 280 | void |
281 | compile_cons(Object *obj) { | ||
282 | printf(" ;; --> compile_cons\n"); | ||
283 | // Store objects into the car and cdr. | ||
284 | compile_object(obj->head); | ||
285 | compile_object(obj->tail->head); | ||
286 | printf(" pop rdx\n"); | ||
287 | printf(" pop rax\n"); | ||
288 | printf(" mov [rsi], rax\n"); | ||
289 | printf(" mov [rsi + 8], rdx\n"); | ||
290 | |||
291 | // Push memory address of cons cell. | ||
292 | printf(" mov rax, rsi\n"); | ||
293 | printf(" or rax, %ld\n", PAIR_TAG); | ||
294 | printf(" push rax\n"); | ||
295 | |||
296 | // Bump allocation register. | ||
297 | printf(" add rsi, 16\n"); | ||
298 | printf(" ;; <-- compile_cons\n"); | ||
299 | } | ||
300 | |||
301 | void | ||
302 | compile_car(Object *obj) { | ||
303 | printf(" ;; <-- compile_car\n"); | ||
304 | compile_object(obj->head); | ||
305 | printf(" pop rax\n"); | ||
306 | printf(" and eax, %ld\n", ~PAIR_MASK); | ||
307 | printf(" mov rdx, [rax]\n"); | ||
308 | printf(" push rdx\n"); | ||
309 | printf(" ;; <-- compile_car\n"); | ||
310 | } | ||
311 | |||
312 | void | ||
313 | compile_cdr(Object *obj) { | ||
314 | printf(" ;; <-- compile_cdr\n"); | ||
315 | compile_object(obj->head); | ||
316 | printf(" pop rax\n"); | ||
317 | printf(" and eax, %ld\n", ~PAIR_MASK); | ||
318 | printf(" mov rdx, [rax + 8]\n"); | ||
319 | printf(" push rdx\n"); | ||
320 | printf(" ;; <-- compile_cdr\n"); | ||
321 | } | ||
322 | |||
323 | void | ||
272 | compile_proc_call(Object *obj) { | 324 | compile_proc_call(Object *obj) { |
273 | // TODO: Probably we want to use a hash table for these lookups that is | 325 | // TODO: Probably we want to use a hash table for these lookups that is |
274 | // initialized at the start of the compilation procedure. | 326 | // initialized at the start of the compilation procedure. |
@@ -310,6 +362,12 @@ compile_proc_call(Object *obj) { | |||
310 | compile_cmp_list(OP_GREATER_EQ, obj->tail); | 362 | compile_cmp_list(OP_GREATER_EQ, obj->tail); |
311 | } else if (sv_equal(&obj->head->text, &STRING("<="))) { | 363 | } else if (sv_equal(&obj->head->text, &STRING("<="))) { |
312 | compile_cmp_list(OP_LESS_EQ, obj->tail); | 364 | compile_cmp_list(OP_LESS_EQ, obj->tail); |
365 | } else if (sv_equal(&obj->head->text, &STRING("cons"))) { | ||
366 | compile_cons(obj->tail); | ||
367 | } else if (sv_equal(&obj->head->text, &STRING("car"))) { | ||
368 | compile_car(obj->tail); | ||
369 | } else if (sv_equal(&obj->head->text, &STRING("cdr"))) { | ||
370 | compile_cdr(obj->tail); | ||
313 | } else { | 371 | } else { |
314 | fprintf(stderr, "error: not implemented\n"); | 372 | fprintf(stderr, "error: not implemented\n"); |
315 | exit(EXIT_FAILURE); | 373 | exit(EXIT_FAILURE); |
@@ -359,12 +417,12 @@ compile(Root *roots) { | |||
359 | printf("%%define FIXNUM_MASK %d\n", FIXNUM_MASK); | 417 | printf("%%define FIXNUM_MASK %d\n", FIXNUM_MASK); |
360 | printf("%%define FIXNUM_TAG %d\n", FIXNUM_TAG); | 418 | printf("%%define FIXNUM_TAG %d\n", FIXNUM_TAG); |
361 | printf("%%define FIXNUM_SHIFT %d\n", FIXNUM_SHIFT); | 419 | printf("%%define FIXNUM_SHIFT %d\n", FIXNUM_SHIFT); |
420 | printf("%%define HEAP_SIZE %ld\n", HEAP_SIZE); | ||
362 | printf("\n"); | 421 | printf("\n"); |
363 | emit_file(PRELUDE_FILE); | 422 | emit_file(PRELUDE_FILE); |
364 | for (size_t i = 0; i < array_size(roots); i++) { | 423 | for (size_t i = 0; i < array_size(roots); i++) { |
365 | Object *root = roots[i]; | 424 | Object *root = roots[i]; |
366 | compile_object(root); | 425 | compile_object(root); |
367 | // OBJ_PRINT(root); | ||
368 | } | 426 | } |
369 | emit_file(POSTLUDE_FILE); | 427 | emit_file(POSTLUDE_FILE); |
370 | } | 428 | } |
diff --git a/src/parser.c b/src/parser.c index 9191aa2..5632e13 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -11,6 +11,7 @@ static char *builtins [] = { | |||
11 | "not", "and", "or", | 11 | "not", "and", "or", |
12 | "nil?", "zero?", "fixnum?", "bool?", | 12 | "nil?", "zero?", "fixnum?", "bool?", |
13 | "display", | 13 | "display", |
14 | "cons", "car", "cdr", | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | uint64_t | 17 | uint64_t |
diff --git a/src/x86_64/postlude.asm b/src/x86_64/postlude.asm index 3355286..37f9df1 100644 --- a/src/x86_64/postlude.asm +++ b/src/x86_64/postlude.asm | |||
@@ -9,3 +9,7 @@ exit: | |||
9 | mov rax, 60 | 9 | mov rax, 60 |
10 | xor rdi, rdi | 10 | xor rdi, rdi |
11 | syscall | 11 | syscall |
12 | |||
13 | section .bss | ||
14 | bdl_heap: | ||
15 | resb HEAP_SIZE | ||
diff --git a/src/x86_64/prelude.asm b/src/x86_64/prelude.asm index 6bb6627..e57e820 100644 --- a/src/x86_64/prelude.asm +++ b/src/x86_64/prelude.asm | |||
@@ -1,3 +1,4 @@ | |||
1 | section .text | ||
1 | printdln: | 2 | printdln: |
2 | sar rdi, FIXNUM_SHIFT | 3 | sar rdi, FIXNUM_SHIFT |
3 | sub rsp, 40 | 4 | sub rsp, 40 |
@@ -98,4 +99,8 @@ display_end: | |||
98 | 99 | ||
99 | global _start | 100 | global _start |
100 | _start: | 101 | _start: |
101 | push NIL_VAL | 102 | ;; point `rdi` to the start of the heap. |
103 | mov rsi, bdl_heap | ||
104 | |||
105 | ;; make sure the last element in the stack is the nil value. | ||
106 | push NIL_VAL | ||