aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-01-16 11:27:23 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2025-01-16 11:27:23 +0200
commit8b8ed7282a0fa5e17b83f0eaae404aa5f231b66a (patch)
tree15ce178c691d2df7829973e595ebdb84732276b1
parent4d812e9b9bcf2530ab5a3275be85365ee277bea8 (diff)
downloadek-8b8ed7282a0fa5e17b83f0eaae404aa5f231b66a.tar.gz
ek-8b8ed7282a0fa5e17b83f0eaae404aa5f231b66a.zip
start adding exported defs
-rw-r--r--include/ek/compiler.h2
-rw-r--r--include/ek/scope.h26
-rw-r--r--include/ek/sptree.h3
-rw-r--r--src/actualize.c67
-rw-r--r--src/ast.c12
-rw-r--r--src/compiler.c82
-rw-r--r--src/scope.c49
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;
};
/**
@@ -105,15 +114,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.
*
* @param scope Scope to set flags for.
@@ -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;
+}