diff options
Diffstat (limited to 'src/parser.c')
-rw-r--r-- | src/parser.c | 32 |
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 | ||
476 | void | 476 | void |
477 | insert_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 | |||
484 | void | ||
477 | semantic_analysis(Environment *env, Object *obj, Errors *errors) { | 485 | semantic_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); |