aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-11-16 18:49:23 +0100
committerBad Diode <bd@badd10de.dev>2021-11-16 18:49:23 +0100
commit0acaf0c98601e7dc8fd401a144ac85b46d040763 (patch)
tree6c2f1b566897a004c521de619b0d570dd26e365b
parent3331c755238e2a12d738ea804232274e1ce4cfc9 (diff)
downloadbdl-0acaf0c98601e7dc8fd401a144ac85b46d040763.tar.gz
bdl-0acaf0c98601e7dc8fd401a144ac85b46d040763.zip
Add proper function calls with closed variables
-rw-r--r--src/compiler.h55
1 files changed, 43 insertions, 12 deletions
diff --git a/src/compiler.h b/src/compiler.h
index e198127..3d61833 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -344,20 +344,46 @@ void
344compile_call(Object *obj) { 344compile_call(Object *obj) {
345 context_printf(" ;; --> compile_call\n"); 345 context_printf(" ;; --> compile_call\n");
346 compile_object(obj->head); 346 compile_object(obj->head);
347 size_t n_args = 0; 347 context_printf(" pop rax\n");
348 context_printf(" mov rcx, PTR_MASK\n");
349 context_printf(" and rcx, rax\n");
350 context_printf(" mov rax, [rcx]\n");
351 context_printf(" push rax\n");
352
353 // Get the number of parameters/captured variables for this function.
354 Object *fun = obj->head;
355 // FIXME: this is horrible and WILL BREAK.
356 while (!IS_LAMBDA(fun)) {
357 if (IS_SYMBOL(fun)) {
358 fun = symbol_in_env(current_env, fun);
359 continue;
360 }
361 if (IS_PAIR(fun)) {
362 fun = fun->head;
363 }
364 }
365
366 size_t n_args = array_size(fun->env->params);
367 size_t n_cap = array_size(fun->env->captured);
368 size_t offset = n_args + n_cap;
369
370 // Push captured variables.
371 for (size_t i = 0; i < n_cap; i++) {
372 context_printf(" mov rax, [rcx + 8 * %zu]\n", i + 1);
373 context_printf(" push rax\n");
374 }
375
376 // Compile arguments.
348 while (obj->tail != NULL) { 377 while (obj->tail != NULL) {
349 obj = obj->tail; 378 obj = obj->tail;
350 compile_object(obj->head); 379 compile_object(obj->head);
351 n_args++;
352 } 380 }
353 context_printf(" mov rax, [rsp + %zu]\n", 8 * n_args); 381
354 context_printf(" mov rcx, PTR_MASK\n"); 382 context_printf(" mov rax, [rsp + %zu]\n", 8 * offset);
355 context_printf(" and rcx, rax\n");
356 context_printf(" mov rax, [rcx]\n");
357 context_printf(" call rax\n"); 383 context_printf(" call rax\n");
358 384
359 // Restore stack to previous location and store the result on top. 385 // Restore stack to previous location and store the result on top.
360 context_printf(" add rsp, %zu\n", 8 * (n_args + 1)); 386 context_printf(" add rsp, %zu\n", 8 * (offset + 1));
361 context_printf(" push rax\n"); 387 context_printf(" push rax\n");
362 context_printf(" ;; <-- compile_call\n"); 388 context_printf(" ;; <-- compile_call\n");
363} 389}
@@ -519,14 +545,13 @@ compile_lambda(Object *obj) {
519 // Add function address. 545 // Add function address.
520 context_printf(" mov rax, %s\n", name); 546 context_printf(" mov rax, %s\n", name);
521 context_printf(" mov [r15], rax\n"); 547 context_printf(" mov [r15], rax\n");
522 context_printf(" mov rax, %ld\n", array_size(obj->env->captured));
523 context_printf(" mov [r15 + 8], rax\n");
524 548
525 // Add captured variables to the heap. 549 // Add captured variables to the heap.
526 for (size_t i = 0; i < array_size(obj->env->captured); i++) { 550 for (size_t i = 0; i < array_size(obj->env->captured); i++) {
527 ssize_t idx = find_var_index(current_env->locals, obj->env->captured[i]); 551 ssize_t idx = find_var_index(current_env->locals, obj->env->captured[i]);
528 context_printf(" mov rax, [rbp + %ld]\n", 8 * idx); 552 context_printf(" mov rax, rbp\n");
529 context_printf(" mov [r15 + %ld], rax\n", 8 * (i + 2)); 553 context_printf(" add rax, %ld\n", 8 * idx);
554 context_printf(" mov [r15 + %ld], rax\n", 8 * (i + 1));
530 // TODO: What about capturing captured variables or parameters? 555 // TODO: What about capturing captured variables or parameters?
531 assert(idx != -1 && "unexpected index"); 556 assert(idx != -1 && "unexpected index");
532 } 557 }
@@ -569,7 +594,13 @@ compile_symbol(Object *obj) {
569 // (display a)) 594 // (display a))
570 idx = find_var_index(current_env->captured, obj); 595 idx = find_var_index(current_env->captured, obj);
571 if (idx != -1) { 596 if (idx != -1) {
572 // TODO: not implemented. 597 size_t n_locals = array_size(current_env->locals);
598 size_t n_params = array_size(current_env->params);
599 size_t n_cap = array_size(current_env->captured);
600 size_t offset = 8 * (n_locals + n_params + n_cap - idx + 1);
601 context_printf(" mov rcx, [rbp + %ld]\n", offset);
602 context_printf(" mov rax, [rcx]\n");
603 context_printf(" push rax\n");
573 context_printf(" ;; <-- compile_symbol\n"); 604 context_printf(" ;; <-- compile_symbol\n");
574 return; 605 return;
575 } 606 }