diff options
author | Bad Diode <bd@badd10de.dev> | 2021-11-16 18:49:23 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-11-16 18:49:23 +0100 |
commit | 0acaf0c98601e7dc8fd401a144ac85b46d040763 (patch) | |
tree | 6c2f1b566897a004c521de619b0d570dd26e365b | |
parent | 3331c755238e2a12d738ea804232274e1ce4cfc9 (diff) | |
download | bdl-0acaf0c98601e7dc8fd401a144ac85b46d040763.tar.gz bdl-0acaf0c98601e7dc8fd401a144ac85b46d040763.zip |
Add proper function calls with closed variables
-rw-r--r-- | src/compiler.h | 55 |
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 | |||
344 | compile_call(Object *obj) { | 344 | compile_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 | } |