From 1cc7990ef7d5483d0434dda412f2d88e0b17df27 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sat, 20 Apr 2024 03:39:40 +0300 Subject: initial working bytecode --- src/scope.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 src/scope.c (limited to 'src/scope.c') diff --git a/src/scope.c b/src/scope.c new file mode 100644 index 0000000..290dfd6 --- /dev/null +++ b/src/scope.c @@ -0,0 +1,153 @@ +#include +#include + +#include +#include +#include + +struct scope { + size_t id; + struct scope *parent; + + const char *fname; + const char *buf; + + struct vec visible; +}; + +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); +} + +void semantic_error(struct scope *scope, struct ast *n, const char *msg, ...) +{ + va_list args; + va_start(args, msg); + struct src_issue issue; + issue.loc = n->loc; + issue.fname = scope->fname; + issue.buf = scope->buf; + vsrc_issue(issue, msg, args); + va_end(args); +} -- cgit v1.2.3