aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ek/ast.h2
-rw-r--r--include/ek/scope.h1
-rw-r--r--src/actualize.c80
-rw-r--r--src/ast.c11
-rw-r--r--src/compiler.c11
-rw-r--r--src/scope.c18
6 files changed, 97 insertions, 26 deletions
diff --git a/include/ek/ast.h b/include/ek/ast.h
index 5c1c6e6..37e644d 100644
--- a/include/ek/ast.h
+++ b/include/ek/ast.h
@@ -197,6 +197,7 @@ enum ast_flags {
AST_FLAG_UFCS_SIMPLE = (1 << 17),
AST_FLAG_UFCS_REF = (1 << 18),
AST_FLAG_UFCS_TRIVIAL = (1 << 19),
+ AST_FLAG_INSTANCE = (1 << 20),
};
struct ast;
@@ -691,6 +692,7 @@ struct ast *ast_prepend(struct ast *list, struct ast *elem);
struct type *type_prepend(struct type *list, struct type *elem);
void ast_set_flags(struct ast *node, enum ast_flags flags);
+void ast_set_flags_recurse(struct ast *node, enum ast_flags flags);
void ast_clear_flags(struct ast *node, enum ast_flags flags);
unsigned ast_flags(struct ast *node, enum ast_flags flags);
diff --git a/include/ek/scope.h b/include/ek/scope.h
index aedeacf..810f1cc 100644
--- a/include/ek/scope.h
+++ b/include/ek/scope.h
@@ -22,6 +22,7 @@ enum scope_flags {
SCOPE_PUBLIC = (1 << 0),
/** Scope is file scope. */
SCOPE_FILE = (1 << 1),
+ SCOPE_ROOT = (1 << 2)
};
struct visible_tuple {
diff --git a/src/actualize.c b/src/actualize.c
index 0d2c624..903d283 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -1201,6 +1201,8 @@ static struct ast *maybe_expand_type(struct scope *scope, struct ast *def,
|| def->k == AST_STRUCT_CONT_DEF
|| def->k == AST_TRAIT_DEF);
+ ast_set_flags_recurse(def, AST_FLAG_INSTANCE);
+
if (def->k == AST_STRUCT_DEF)
return maybe_expand_struct(scope, def, loc, args);
else if (def->k == AST_STRUCT_CONT_DEF)
@@ -1432,6 +1434,40 @@ static int undefined_gotos(struct act_state *state, struct scope *scope)
return ret;
}
+struct exported_helper {
+ struct scope *scope;
+ struct ast *node;
+};
+
+static int _check_exported(struct type *type, struct exported_helper *helper)
+{
+ struct ast *def = type->d;
+ if (!def)
+ return 0;
+
+ struct ast *node = helper->node;
+ struct scope *scope = helper->scope;
+
+ if (is_exported_type(scope, def))
+ return 0;
+
+ char *tstr = type_str(type);
+ semantic_error(node->scope->fctx, node,
+ "type %s should be exported",
+ tstr);
+ free(tstr);
+ return -1;
+}
+
+static int check_exported(struct scope *scope, struct ast *node ,struct type *type)
+{
+ struct exported_helper helper = {
+ .scope = scope,
+ .node = node
+ };
+ return type_visit((type_callback_t)_check_exported, NULL, type, &helper);
+}
+
static int actualize_proc_sign(struct scope *scope, struct ast *proc)
{
assert(proc && proc->k == AST_PROC_DEF);
@@ -1440,6 +1476,11 @@ static int actualize_proc_sign(struct scope *scope, struct ast *proc)
proc->scope = create_scope();
scope_add_scope(scope, proc->scope);
+ foreach_node(p, proc_params(proc)) {
+ if (ast_flags(proc, AST_FLAG_PUBLIC))
+ ast_set_flags(p, AST_FLAG_PUBLIC);
+ }
+
if (actualize_list(&new_state, proc->scope, proc_params(proc))) {
destroy_act_state(&new_state);
return -1;
@@ -1454,6 +1495,12 @@ static int actualize_proc_sign(struct scope *scope, struct ast *proc)
return -1;
}
+ if (ast_flags(proc, AST_FLAG_PUBLIC) && !ast_flags(proc, AST_FLAG_INSTANCE))
+ foreach_type(t, rtype) {
+ if (check_exported(scope, proc, t))
+ return -1;
+ }
+
struct type *callable = tgen_callable(NULL, rtype, proc->loc);
foreach_node(p, proc_params(proc)) {
/* we must manually 'start' the chain */
@@ -1684,6 +1731,11 @@ static int actualize_var(struct act_state *state,
/* declare */
set_type(var, type);
+ if (ast_flags(var, AST_FLAG_PUBLIC) && !ast_flags(var, AST_FLAG_INSTANCE)) {
+ if (check_exported(scope, var, var->t))
+ return -1;
+ }
+
/* an unnamed var is a var in a signature that should not produce a
* warning on not being used (if I ever get around to adding those kinds
* of warnings) */
@@ -2485,18 +2537,6 @@ static int expand_struct_body(struct act_state *state,
if (actualize_type(&type_state, scope, type))
return -1;
- if (ast_flags(node, AST_FLAG_PUBLIC)) {
- 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 && !is_exported_type(scope,
- def)) {
- semantic_error(struct_scope->fctx, n,
- "trait used in pub def must also be exported");
- return -1;
- }
- }
-
type_append(&types, type);
struct ast *alias = gen_alias(strdup(id), type, n->loc);
@@ -2507,6 +2547,19 @@ static int expand_struct_body(struct act_state *state,
if (actualize(&state, struct_scope, alias))
return -1;
+ if (!ast_flags(node, AST_FLAG_PUBLIC))
+ continue;
+
+ if (ast_flags(node, AST_FLAG_INSTANCE))
+ continue;
+
+ struct ast *def = type->d;
+ if (is_exported_type(scope, def))
+ continue;
+
+ semantic_error(struct_scope->fctx, n,
+ "trait used in pub def must also be exported");
+ return -1;
}
if (node->k == AST_STRUCT_CONT_DEF
@@ -2608,6 +2661,9 @@ static int expand_struct_body(struct act_state *state,
if (n->k == AST_TYPE_EXPAND)
continue;
+ if (ast_flags(node, AST_FLAG_PUBLIC))
+ ast_set_flags(n, AST_FLAG_PUBLIC);
+
struct act_state state = {0};
if (actualize(&state, struct_scope, n))
return -1;
diff --git a/src/ast.c b/src/ast.c
index c7f32a0..5561745 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -149,6 +149,17 @@ void ast_set_flags(struct ast *node, enum ast_flags flags)
node->f |= flags;
}
+static int _ast_set_flags(struct ast *node, enum ast_flags *flags)
+{
+ ast_set_flags(node, *flags);
+ return 0;
+}
+
+void ast_set_flags_recurse(struct ast *node, enum ast_flags flags)
+{
+ ast_visit((ast_callback_t)_ast_set_flags, NULL, node, &flags);
+}
+
void ast_clear_flags(struct ast *node, enum ast_flags flags)
{
node->f &= ~(flags);
diff --git a/src/compiler.c b/src/compiler.c
index 881326c..d865ea5 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -171,13 +171,14 @@ struct scope *process_file(const char *file)
return *exists;
} else {
struct scope *scope = create_scope();
- if (process(scope, base)) {
- destroy_scope(scope);
- free(real);
- goto out;
- }
+ if (scopes_len(&scopes) == 0)
+ scope_set_flags(scope, SCOPE_ROOT);
scopes_insert(&scopes, real, scope);
+
+ if (process(scope, base))
+ goto out;
+
res_destroy(r);
return scope;
}
diff --git a/src/scope.c b/src/scope.c
index 1eae065..4c9097f 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -17,12 +17,6 @@
#include <ek/scope.h>
#include <ek/actualize.h>
-static bool same_src_scope(struct scope *a, struct scope *b)
-{
- /** @todo a bit ridiculous, is there a less hacky way? */
- return a->fctx.fbuf == b->fctx.fbuf;
-}
-
struct scope *create_scope()
{
/* if I ever try making the parser multithreaded, this should be atomic. */
@@ -123,9 +117,6 @@ static bool scope_add_recurse(struct scope *scope, struct ast *node)
if (!ast_flags(node, AST_FLAG_PUBLIC))
return false;
- if (same_src_scope(scope, node->scope))
- return true;
-
return scope_flags(scope, SCOPE_PUBLIC);
}
@@ -459,6 +450,9 @@ void scope_add_scope(struct scope *parent, struct scope *child)
bool is_exported_type(struct scope *scope, struct ast *def)
{
+ if (scope_flags(scope, SCOPE_ROOT))
+ return true;
+
struct ast **found = exported_find(&scope->exported_types, def);
if (found)
return true;
@@ -471,6 +465,9 @@ bool is_exported_type(struct scope *scope, struct ast *def)
bool is_exported_symbol(struct scope *scope, struct ast *def)
{
+ if (scope_flags(scope, SCOPE_ROOT))
+ return true;
+
struct ast **found = exported_find(&scope->exported_symbols, def);
if (found)
return true;
@@ -483,6 +480,9 @@ bool is_exported_symbol(struct scope *scope, struct ast *def)
bool is_exported_macro(struct scope *scope, struct ast *def)
{
+ if (scope_flags(scope, SCOPE_ROOT))
+ return true;
+
struct ast **found = exported_find(&scope->exported_macros, def);
if (found)
return true;