/* SPDX-License-Identifier: copyleft-next-0.3.1 */ /* Copyright 2024 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ /** @file scope.c * * Implementations for scope handling stuff. */ #include #include #include #include #include #include #include #include #include struct scope *create_scope() { /* if I ever try making the parser multithreaded, this should be atomic. */ static size_t counter = 0; struct scope *scope = calloc(1, sizeof(struct scope)); if (!scope) { internal_error("ran out of memory allocating scope"); return NULL; } scope->number = counter++; scope->symbols = visible_create(16); /* arbitrary number */ scope->templates = visible_create(0); scope->traits = visible_create(0); scope->types = visible_create(0); scope->mods = mod_vec_create(0); return scope; } void destroy_scope(struct scope *scope) { if (!scope) return; if (!scope->parent) { free((void *)scope->fctx.fbuf); free((void *)scope->fctx.fname); } foreach(mod_vec, m, &scope->mods) { dlclose(*m); } mod_vec_destroy(&scope->mods); visible_destroy(&scope->symbols); visible_destroy(&scope->templates); visible_destroy(&scope->traits); visible_destroy(&scope->types); struct scope *prev = scope->children, *cur; if (prev) do { cur = prev->next; destroy_scope(prev); } while ((prev = cur)); free(scope); } int scope_add_symbol(struct scope *scope, struct ast *symbol) { assert(symbol->k == AST_VAR_DEF || symbol->k == AST_PROC_DEF); struct ast **exists = visible_insert(&scope->symbols, symbol->s, symbol); if (!exists) { internal_error("failed inserting symbol into scope"); return -1; } if (*exists != symbol) { semantic_error(scope, symbol, "symbol redefined"); semantic_info(scope, *exists, "previously here"); return -1; } return 0; } struct ast *scope_find_symbol(struct scope *scope, char *id) { struct ast **v = visible_find(&scope->symbols, id); if (!v) return NULL; return *v; } struct ast *file_scope_find_symbol(struct scope *scope, char *id) { if (!scope) return NULL; struct ast *found = scope_find_symbol(scope, id); if (found) return found; return file_scope_find_symbol(scope->parent, id); } int scope_add_type(struct scope *scope, struct ast *type) { assert(type->k == AST_STRUCT_DEF); struct ast **exists = visible_insert(&scope->types, type->s, type); if (!exists) { internal_error("failed inserting type into scope"); return -1; } if (*exists != type) { semantic_error(scope, type, "type redefined"); semantic_info(scope, *exists, "previously here"); return -1; } return 0; } struct ast *scope_find_type(struct scope *scope, char *id) { struct ast **v = visible_find(&scope->types, id); if (!v) return NULL; return *v; } struct ast *file_scope_find_type(struct scope *scope, char *id) { if (!scope) return NULL; struct ast *found = scope_find_type(scope, id); if (found) return found; return file_scope_find_type(scope->parent, id); } int scope_add_trait(struct scope *scope, struct ast *trait) { assert(trait->k == AST_TRAIT_DEF); struct ast **exists = visible_insert(&scope->traits, trait->s, trait); if (!exists) { internal_error("failed inserting trait into scope"); return -1; } if (*exists != trait) { semantic_error(scope, trait, "trait redefined"); semantic_info(scope, *exists, "previously here"); return -1; } return 0; } struct ast *scope_find_trait(struct scope *scope, char *id) { struct ast **v = visible_find(&scope->traits, id); if (!v) return NULL; return *v; } struct ast *file_scope_find_trait(struct scope *scope, char *id) { if (!scope) return NULL; struct ast *found = scope_find_trait(scope, id); if (found) return found; return file_scope_find_trait(scope->parent, id); } int scope_add_template(struct scope *scope, struct ast *template) { struct ast **exists = visible_insert(&scope->templates, template->s, template); if (!exists) { internal_error("failed inserting template into scope"); return -1; } if (*exists != template) { semantic_error(scope, template, "template redefined"); semantic_info(scope, *exists, "previously here"); return -1; } return 0; } struct ast *scope_find_template(struct scope *scope, char *id) { struct ast **v = visible_find(&scope->templates, id); if (!v) return NULL; return *v; } struct ast *file_scope_find_template(struct scope *scope, char *id) { if (!scope) return NULL; struct ast *found = scope_find_template(scope, id); if (found) return found; return file_scope_find_template(scope->parent, id); } void scope_add_scope(struct scope *parent, struct scope *child) { assert(parent); assert(child); child->fctx = parent->fctx; child->parent = parent; child->next = parent->children; parent->children = child; }