diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/scope.c | 123 | ||||
-rw-r--r-- | src/scope.h | 46 |
2 files changed, 169 insertions, 0 deletions
diff --git a/src/scope.c b/src/scope.c new file mode 100644 index 0000000..de1295e --- /dev/null +++ b/src/scope.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2023 Carlos Maniero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +#include "scope.h" +#include <errno.h> +#include <stdio.h> +#include <string.h> + +static scope_item_t * +scope_item_new() +{ + scope_item_t *item = malloc(sizeof(scope_item_t)); + if (item == NULL) { + fprintf(stderr, "failed to create scope item: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + return item; +} + +static void +scope_item_destroy(scope_item_t *item) +{ + free(item); +} + +scope_t * +scope_new() +{ + scope_t *scope = malloc(sizeof(scope_t)); + + if (scope == NULL) { + fprintf(stderr, "failed to create scope: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + scope->stack = vector_new(); + scope_enter(scope); + return scope; +} + +void +scope_destroy(scope_t *scope) +{ + if (scope->stack->size) { + fprintf(stderr, + "Stack not cleaned before destroying. This may lead to memory leaks.\n" + "Please make sure to call the leave function before destroying it."); + } + + for (size_t i = 0; i < scope->stack->size; i++) { + vector_destroy(vector_at(scope->stack, i)); + } + + vector_destroy(scope->stack); + free(scope); +} + +void +scope_enter(scope_t *scope) +{ + vector_push_back(scope->stack, vector_new()); +} + +void +scope_leave(scope_t *scope) +{ + // FIXME: create a stack data structure to simplify this logic + vector_t *new_stack = vector_new(); + + for (size_t i = 0; i < scope->stack->size - 1; i++) { + vector_push_back(new_stack, vector_at(scope->stack, i)); + } + + vector_t *current_level = vector_at(scope->stack, scope->stack->size - 1); + + for (size_t i = 0; i < current_level->size; i++) { + scope_item_destroy(vector_at(current_level, i)); + } + + vector_destroy(current_level); + vector_t *old_stack = scope->stack; + vector_destroy(old_stack); + scope->stack = new_stack; +} + +ast_node_t * +scope_get(scope_t *scope, ast_identifier_t *identifier) +{ + for (size_t i = scope->stack->size; i > 0; i--) { + vector_t *current_level = vector_at(scope->stack, i - 1); + + for (size_t j = 0; j < current_level->size; j++) { + scope_item_t *item = vector_at(current_level, j); + + if (string_view_eq(identifier->name, item->identifier->name)) { + return item->node; + } + } + } + + return NULL; +} +void +scope_push(scope_t *scope, ast_identifier_t *identifier, ast_node_t *node) +{ + vector_t *current_level = vector_at(scope->stack, scope->stack->size - 1); + scope_item_t *item = scope_item_new(); + *item = (scope_item_t){ .identifier = identifier, .node = node }; + vector_push_back(current_level, item); +} diff --git a/src/scope.h b/src/scope.h new file mode 100644 index 0000000..bce3567 --- /dev/null +++ b/src/scope.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 Carlos Maniero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +#include "ast.h" +#include "string_view.h" +#include "vector.h" + +typedef struct scope_t +{ + vector_t *stack; +} scope_t; + +typedef struct scope_item_t +{ + ast_identifier_t *identifier; + ast_node_t *node; +} scope_item_t; + +scope_t * +scope_new(); + +void +scope_destroy(scope_t *scope); + +void +scope_enter(scope_t *scope); +void +scope_leave(scope_t *scope); + +ast_node_t * +scope_get(scope_t *scope, ast_identifier_t *identifier); +void +scope_push(scope_t *scope, ast_identifier_t *identifier, ast_node_t *node); |