/* * 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 . */ #include "scope.h" #include #include #include static scope_item_t * scope_item_new(void) { 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(void) { 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 != 1) { 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, string_view_t name) { 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(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); }