aboutsummaryrefslogtreecommitdiffstats
path: root/src/parser.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-11-15 22:33:53 +0100
committerBad Diode <bd@badd10de.dev>2021-11-15 22:33:53 +0100
commit62984fb580b9e355cf9eacf9de53bff8c895c0b5 (patch)
tree913df113b13d66328262dc5075f2b9925db46c4a /src/parser.c
parent26f1b9c35d337c0814158077fdc8f56b817e0b14 (diff)
downloadbdl-62984fb580b9e355cf9eacf9de53bff8c895c0b5.tar.gz
bdl-62984fb580b9e355cf9eacf9de53bff8c895c0b5.zip
Add initial boilerplate for closure capture
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/src/parser.c b/src/parser.c
index 0968ccd..e72675f 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -474,6 +474,14 @@ insert_params(Environment *env, Object *symbol) {
474} 474}
475 475
476void 476void
477insert_captured(Environment *env, Object *symbol) {
478 if (find_var_index(env->captured, symbol) != -1) {
479 return;
480 }
481 array_push(env->captured, symbol);
482}
483
484void
477semantic_analysis(Environment *env, Object *obj, Errors *errors) { 485semantic_analysis(Environment *env, Object *obj, Errors *errors) {
478 if (obj == NULL || obj->visited) { 486 if (obj == NULL || obj->visited) {
479 return; 487 return;
@@ -481,7 +489,27 @@ semantic_analysis(Environment *env, Object *obj, Errors *errors) {
481 obj->visited = true; 489 obj->visited = true;
482 switch (obj->type) { 490 switch (obj->type) {
483 case OBJ_TYPE_SYMBOL: { 491 case OBJ_TYPE_SYMBOL: {
484 Object *found = symbol_in_env(env, obj); 492 Object *found = NULL;
493
494 Environment *cur_env = env;
495 while (cur_env != NULL) {
496 ssize_t idx = find_var_index(cur_env->locals, obj);
497 if (idx != -1) {
498 found = cur_env->local_values[idx];
499 if (cur_env != env && cur_env->parent != NULL) {
500 insert_captured(env, obj);
501 }
502 break;
503 }
504 idx = find_var_index(cur_env->params, obj);
505 if (idx != -1) {
506 found = cur_env->params[idx];
507 break;
508 }
509 cur_env = cur_env->parent;
510 }
511
512 // Check if symbol is in other environments.
485 if (found == NULL) { 513 if (found == NULL) {
486 error_push(errors, (Error){ 514 error_push(errors, (Error){
487 .type = ERR_TYPE_PARSER, 515 .type = ERR_TYPE_PARSER,
@@ -645,6 +673,7 @@ env_alloc(Environment *parent) {
645 array_init(env->locals, 0); 673 array_init(env->locals, 0);
646 array_init(env->local_values, 0); 674 array_init(env->local_values, 0);
647 array_init(env->params, 0); 675 array_init(env->params, 0);
676 array_init(env->captured, 0);
648 env->parent = parent; 677 env->parent = parent;
649 array_push(environments, env); 678 array_push(environments, env);
650 return env; 679 return env;
@@ -687,6 +716,7 @@ free_objects(void) {
687 array_free(env->locals); 716 array_free(env->locals);
688 array_free(env->local_values); 717 array_free(env->local_values);
689 array_free(env->params); 718 array_free(env->params);
719 array_free(env->captured);
690 free(env); 720 free(env);
691 } 721 }
692 array_free(environments); 722 array_free(environments);