From 8b8ed7282a0fa5e17b83f0eaae404aa5f231b66a Mon Sep 17 00:00:00 2001 From: Kimplul Date: Thu, 16 Jan 2025 11:27:23 +0200 Subject: start adding exported defs --- include/ek/compiler.h | 2 +- include/ek/scope.h | 26 ++++++++-------- include/ek/sptree.h | 3 ++ src/actualize.c | 67 ++++++++++++++++++++++++----------------- src/ast.c | 12 ++++---- src/compiler.c | 82 +++++++++++++-------------------------------------- src/scope.c | 49 ++++++++++++++++++++++++++++-- 7 files changed, 129 insertions(+), 112 deletions(-) diff --git a/include/ek/compiler.h b/include/ek/compiler.h index cbe34e2..4afddb6 100644 --- a/include/ek/compiler.h +++ b/include/ek/compiler.h @@ -31,6 +31,6 @@ int compile(const char *input); * @param file File to process. * @return \c 0 if compilation was succesful, otherwise some non-zero value. */ -int process_file(struct scope **parent, int public, const char *file); +struct scope *process_file(const char *file); #endif /* EK_COMPILER_H */ diff --git a/include/ek/scope.h b/include/ek/scope.h index ab27cc6..d8a5974 100644 --- a/include/ek/scope.h +++ b/include/ek/scope.h @@ -55,6 +55,11 @@ static inline int expanded_key_cmp(struct expanded_key a, struct expanded_key b) #define MAP_NAME expanded #include "map.h" +#define SPTREE_TYPE struct ast * +#define SPTREE_CMP(a, b) ((uintptr_t)(a) - (uintptr_t)(b)) +#define SPTREE_NAME exported +#include "sptree.h" + /** * Scope. * Responsible for keeping track of visibilities and @@ -87,6 +92,10 @@ struct scope { struct visible symbols; struct visible macros; struct visible types; + + struct exported exported_symbols; + struct exported exported_macros; + struct exported exported_types; }; /** @@ -104,15 +113,6 @@ struct scope *create_scope(); */ void destroy_scope(struct scope *scope); -/** - * Add a scratch AST node. - * - * @param scope Scope to add scratch AST node to. - * @param scratch Scratch node to add to \p scope. - * @return \c 0 when successful, non-zero otherwise. - */ -int scope_add_scratch(struct scope *scope, struct ast *scratch); - /** * Set scope flags. * @@ -336,10 +336,8 @@ struct ast *file_scope_find_trait(struct scope *scope, char *id); struct ast *file_scope_find_expd_struct(struct scope *scope, struct ast *def, struct type *types); -#define foreach_visible(iter, init) \ - for (struct visible *iter = init; iter; iter = iter->next) - -#define foreach_expanded(iter, init) \ - for (struct expanded *iter = init; iter; iter = iter->next) +bool is_exported_type(struct scope *scope, struct ast *def); +bool is_exported_symbol(struct scope *scope, struct ast *def); +bool is_exported_macro(struct scope *scope, struct ast *def); #endif /* SCOPE_H */ diff --git a/include/ek/sptree.h b/include/ek/sptree.h index 8dfdfbf..8ba6d6c 100644 --- a/include/ek/sptree.h +++ b/include/ek/sptree.h @@ -73,6 +73,9 @@ static inline struct SPNODE *SPTREE(last)(struct SPNODE *n) static inline SPTREE_TYPE *SPTREE(begin)(struct SPROOT *s) { + if (SPTREE(len)(s) == 0) + return NULL; + return &SPTREE(first)(s->root)->data; } diff --git a/src/actualize.c b/src/actualize.c index ebbffbb..941f9e3 100644 --- a/src/actualize.c +++ b/src/actualize.c @@ -327,6 +327,32 @@ static int eval_const_if(struct scope *scope, struct ast *node) static int actualize_proc_sign(struct scope *scope, struct ast *proc); +static int copy_scope(struct scope *to, struct scope *from) +{ + /** @todo handle duplicates */ + foreach(visible, n, &from->symbols) { + struct ast *def = n->data; + if (!ast_flags(def, AST_FLAG_PUBLIC)) + continue; + + switch (def->k) { + case AST_PROC_DEF: + if (scope_add_proc(to, def)) + return -1; + break; + + case AST_VAR_DEF: + if (scope_add_var(to, def)) + return -1; + break; + + default: abort(); + } + } + + return 0; +} + static int analyze_visibility(struct scope *scope, struct ast *node) { if (!node) @@ -343,17 +369,19 @@ static int analyze_visibility(struct scope *scope, struct ast *node) case AST_IMPORT: { const char *file = import_file(node); - int ret = process_file(&scope, - (int)ast_flags(node, AST_FLAG_PUBLIC), - file); + struct scope *child = process_file(file); - if (ret == 0) - return 0; + if (!child) { + semantic_info(scope->fctx, node, "imported here"); + return -1; + } - /** @todo should maybe make this some other type of error, kind - * of too busy atm */ - semantic_info(scope->fctx, node, "imported here"); - return ret; + if (copy_scope(scope, child)) { + semantic_info(scope->fctx, node, "imported here"); + return -1; + } + + return 0; } case AST_IF: { @@ -2118,22 +2146,6 @@ static int params_match(struct scope *scope, struct ast *base, struct ast *node) return 1; } -/* slightly hacky but works well enough for now */ -static int trait_exported(struct scope *scope, struct ast *def) -{ - assert(file_scope_find_type(scope, def->s) == def); - - while (!scope_flags(scope, SCOPE_FILE) && scope->parent) - scope = scope->parent; - - assert(scope && scope_flags(scope, SCOPE_FILE)); - struct scope *parent = scope->parent; - if (!parent) - return true; - - return file_scope_find_type(parent, def->s) == def; -} - static int expand_struct_body(struct act_state *state, struct scope *scope, struct ast *node, @@ -2185,9 +2197,10 @@ static int expand_struct_body(struct act_state *state, struct ast *def = type->d; /* traits should only show up during the initial * expansion, but should maybe make sure somehow */ - if (def->k == AST_TRAIT_DEF && !trait_exported(scope, def)) { + if (def->k == AST_TRAIT_DEF && !is_exported_type(scope, + def)) { semantic_error(struct_scope->fctx, n, - "trait used in pub def must also be exported"); + "trait used in pub def must also be exported"); return -1; } } diff --git a/src/ast.c b/src/ast.c index 5ba8000..e4254da 100644 --- a/src/ast.c +++ b/src/ast.c @@ -424,15 +424,15 @@ struct ast *clone_ast(struct ast *n) /* don't clone defers */ if (!(n->k == AST_BLOCK)) - if (n->a1) - new->a1 = clone_ast_list(n->a1); + if (n->a1) + new->a1 = clone_ast_list(n->a1); /* don't clone expanded body, just the raw one */ if (!(n->k == AST_TRAIT_DEF - || n->k == AST_STRUCT_DEF - || n->k == AST_STRUCT_CONT_DEF)) - if (n->a2) - new->a2 = clone_ast_list(n->a2); + || n->k == AST_STRUCT_DEF + || n->k == AST_STRUCT_CONT_DEF)) + if (n->a2) + new->a2 = clone_ast_list(n->a2); if (n->a3) new->a3 = clone_ast_list(n->a3); diff --git a/src/compiler.c b/src/compiler.c index 7ce6167..b4a6e9b 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -67,7 +67,7 @@ static char *read_file(const char *file, FILE *f) * @param file File name to process. * @return \c 0 if processing was succesful, non-zero value otherwise. */ -static int process(struct scope **parent, int public, const char *file) +static int process(struct scope *scope, const char *file) { FILE *f = fopen(file, "rb"); if (!f) { @@ -99,24 +99,10 @@ static int process(struct scope **parent, int public, const char *file) ast_dump_list(0, tree); - struct scope *scope = create_scope(); - if (!scope) { - free((void *)buf); - return -1; - } - - if (public) - scope_set_flags(scope, SCOPE_PUBLIC); - scope->fctx.fbuf = buf; scope->fctx.fname = strdup(file); scope_set_flags(scope, SCOPE_FILE); - if (*parent) - scope_add_scope(*parent, scope); - else - *parent = scope; - if (analyze_root(scope, tree)) return -1; @@ -129,52 +115,26 @@ static int process(struct scope **parent, int public, const char *file) #define MAP_NAME scopes #include "ek/map.h" -static int copy_scope(struct scope *to, struct scope *from) -{ - /** @todo handle duplicates */ - foreach(visible, n, &from->symbols) { - struct ast *def = n->data; - if (!ast_flags(def, AST_FLAG_PUBLIC)) - continue; - - switch (def->k) { - case AST_PROC_DEF: - if (scope_add_proc(to, def)) - return -1; - break; - - case AST_VAR_DEF: - if (scope_add_var(to, def)) - return -1; - break; - - default: abort(); - } - } - - return 0; -} - /* ugly global for now */ static struct scopes scopes; static void destroy_scopes() { if (scopes_len(&scopes)) - foreach(scopes, n, &scopes) { - free(n->key); - } + foreach(scopes, n, &scopes) { + destroy_scope(n->data); + free(n->key); + } scopes_destroy(&scopes); } -int process_file(struct scope **scope, int public, const char *file) +struct scope *process_file(const char *file) { - int res = -1; /** todo report failure allocating stuff maybe? */ struct res *r = res_create(); if (!r) - return -1; + return NULL; const char *base = ek_basename(file); res_add(r, (void *)base); @@ -203,37 +163,39 @@ int process_file(struct scope **scope, int public, const char *file) struct scope **exists = scopes_find(&scopes, real); if (exists) { - if (copy_scope(*scope, *exists)) - goto out; - + res_destroy(r); free(real); + return *exists; } else { - if (process(scope, public, base)) + struct scope *scope = create_scope(); + if (process(scope, base)) { + destroy_scope(scope); + free(real); goto out; + } - scopes_insert(&scopes, real, *scope); + scopes_insert(&scopes, real, scope); + res_destroy(r); + return scope; } if (chdir(cwd)) { error("couldn't change back to directory %s: %s\n", cwd, - strerror( - errno)); + strerror(errno)); goto out; } - res = 0; out: res_destroy(r); - return res; + return NULL; } int compile(const char *input) { scopes = scopes_create(); int ret = -1; - struct scope *root = NULL; - if (process_file(&root, 0, input)) { - destroy_scope(root); + struct scope *root = process_file(input); + if (!root) { destroy_allocs(); destroy_scopes(); error("compilation of %s stopped due to errors", input); @@ -241,14 +203,12 @@ int compile(const char *input) { } if ((ret = lower(root))) { - destroy_scope(root); destroy_allocs(); destroy_scopes(); error("compilation of %s stopped due to errors", input); return ret; } - destroy_scope(root); destroy_allocs(); destroy_scopes(); return 0; diff --git a/src/scope.c b/src/scope.c index 52028a8..282018c 100644 --- a/src/scope.c +++ b/src/scope.c @@ -39,6 +39,10 @@ struct scope *create_scope() scope->macros = visible_create(); scope->types = visible_create(); + scope->exported_symbols = exported_create(); + scope->exported_macros = exported_create(); + scope->exported_types = exported_create(); + scope->number = counter++; return scope; } @@ -59,9 +63,12 @@ void destroy_scope(struct scope *scope) expanded_destroy(&scope->expanded); + exported_destroy(&scope->exported_symbols); + exported_destroy(&scope->exported_macros); + exported_destroy(&scope->exported_types); + struct scope *prev = scope->children, *cur; - if (prev) - do { + if (prev) do { cur = prev->next; destroy_scope(prev); } while ((prev = cur)); @@ -87,7 +94,7 @@ struct ast **create_type(struct scope *scope, char *id, struct ast *type) } struct ast **create_expanded(struct scope *scope, struct ast *def, - struct type *types, struct ast *expd) + struct type *types, struct ast *expd) { struct expanded_key key = {.def = def, .types = types}; return expanded_insert(&scope->expanded, key, expd); @@ -449,3 +456,39 @@ void scope_add_scope(struct scope *parent, struct scope *child) child->next = parent->children; parent->children = child; } + +bool is_exported_type(struct scope *scope, struct ast *def) +{ + struct ast **found = exported_find(&scope->exported_types, def); + if (found) + return true; + + if (scope->parent) + return is_exported_type(scope->parent, def); + + return false; +} + +bool is_exported_symbol(struct scope *scope, struct ast *def) +{ + struct ast **found = exported_find(&scope->exported_symbols, def); + if (found) + return true; + + if (scope->parent) + return is_exported_symbol(scope->parent, def); + + return false; +} + +bool is_exported_macro(struct scope *scope, struct ast *def) +{ + struct ast **found = exported_find(&scope->exported_macros, def); + if (found) + return true; + + if (scope->parent) + return is_exported_macro(scope->parent, def); + + return false; +} -- cgit v1.3