#include #include #include #include #include #include struct vec scopes = {0}; struct scope *create_scope() { static size_t counter = 0; if (vec_uninit(scopes)) { scopes = vec_create(sizeof(struct scope *)); } struct scope *scope = calloc(1, sizeof(struct scope)); if (!scope) return NULL; scope->visible = vec_create(sizeof(struct ast *)); scope->id = counter++; vect_append(struct scope *, scopes, &scope); return scope; } void scope_add_scope(struct scope *parent, struct scope *scope) { scope->parent = parent; scope->fname = parent->fname; scope->buf = parent->buf; } void scope_set_file(struct scope *scope, const char *fname, const char *buf) { scope->fname = fname; scope->buf = buf; } struct ast *scope_find(struct scope *scope, char *id) { /* not particularly fast, but good enough for now */ foreach_vec(vi, scope->visible) { struct ast *n = vect_at(struct ast *, scope->visible, vi); if (same_id(n->id, id)) return n; } return NULL; } struct ast *file_scope_find(struct scope *scope, char *id) { struct ast *exists = scope_find(scope, id); if (exists) return exists; if (scope->parent) return file_scope_find(scope->parent, id); return NULL; } int scope_add_var(struct scope *scope, struct ast *var) { struct ast *exists = scope_find(scope, var_id(var)); if (exists) { semantic_error(scope, var, "var redefined"); semantic_error(scope, exists, "previously here"); return -1; } vect_append(struct ast *, scope->visible, &var); return 0; } int scope_add_formal(struct scope *scope, struct ast *formal) { struct ast *exists = scope_find(scope, formal_id(formal)); if (exists) { semantic_error(scope, formal, "formal redefined"); semantic_error(scope, exists, "previously here"); return -1; } vect_append(struct ast *, scope->visible, &formal); return 0; } int scope_add_proc(struct scope *scope, struct ast *proc) { struct ast *exists = scope_find(scope, proc_id(proc)); if (exists) { semantic_error(scope, proc, "proc redefined"); semantic_error(scope, exists, "previously here"); return -1; } vect_append(struct ast *, scope->visible, &proc); return 0; } int scope_add_func(struct scope *scope, struct ast *func) { struct ast *exists = scope_find(scope, func_id(func)); if (exists) { semantic_error(scope, func, "func redefined"); semantic_error(scope, exists, "previously here"); return -1; } vect_append(struct ast *, scope->visible, &func); return 0; } static void destroy_scope(struct scope *scope) { vec_destroy(&scope->visible); free(scope); } void destroy_scopes() { foreach_vec(si, scopes) { struct scope *s = vect_at(struct scope *, scopes, si); destroy_scope(s); } vec_destroy(&scopes); }