aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c32
-rw-r--r--src/ast.c2
-rw-r--r--src/scope.c58
3 files changed, 69 insertions, 23 deletions
diff --git a/src/actualize.c b/src/actualize.c
index 7f590c3..e17305c 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -343,9 +343,17 @@ static int analyze_visibility(struct scope *scope, struct ast *node)
case AST_IMPORT: {
const char *file = import_file(node);
- return process_file(&scope,
+ int ret = process_file(&scope,
(int)ast_flags(node, AST_FLAG_PUBLIC),
file);
+
+ if (ret == 0)
+ return 0;
+
+ /** @todo should maybe make this some other type of error, kind
+ * of too busy atm */
+ semantic_info(scope->fctx, node, "imported here");
+ return ret;
}
case AST_IF: {
@@ -823,6 +831,26 @@ static int expand_chain(struct ast *expd, struct ast *params,
return expand_type(expd, params, types);
}
+static struct ast *chain_graft(struct ast *exists, struct ast *def,
+ struct ast *params, struct type *types)
+{
+ if (same_src(exists, def))
+ return exists;
+
+ assert(def->chain);
+ struct ast *graft = chain_graft(exists, def->chain, params, types);
+ if (!graft)
+ return NULL;
+
+ struct ast *new = clone_ast(def);
+ new->chain = graft;
+
+ if (expand_type(new, params, types))
+ return NULL;
+
+ return new;
+}
+
static struct ast *maybe_expand_struct_cont(struct scope *scope,
struct ast *def,
struct src_loc loc,
@@ -842,7 +870,7 @@ static struct ast *maybe_expand_struct_cont(struct scope *scope,
struct ast *exists = file_scope_find_expd_struct(scope, base, args);
if (exists)
- return exists;
+ return chain_graft(exists, def, struct_params(base), args);
if (!should_implement_list(scope, struct_params(base), loc, args))
return NULL;
diff --git a/src/ast.c b/src/ast.c
index 0571c12..5cfafdd 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -150,7 +150,7 @@ void ast_clear_flags(struct ast *node, enum ast_flags flags)
unsigned ast_flags(struct ast *node, enum ast_flags flags)
{
- return node->f & flags;
+ return (node->f & flags) == flags;
}
void ast_append(struct ast **list, struct ast *elem)
diff --git a/src/scope.c b/src/scope.c
index 198e2c0..6687d98 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -17,6 +17,12 @@
#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. */
@@ -87,7 +93,7 @@ void scope_set_flags(struct scope *scope, enum scope_flags flags)
unsigned scope_flags(struct scope *scope, enum scope_flags flags)
{
assert(scope);
- return scope->flags & flags;
+ return (scope->flags & flags) == flags;
}
static struct visible *create_visible(char *id, struct ast *node)
@@ -166,6 +172,20 @@ struct visible *create_proc(struct scope *scope, char *id, struct ast *proc)
return n;
}
+static bool scope_add_recurse(struct scope *scope, struct ast *node)
+{
+ if (!scope->parent)
+ return false;
+
+ if (!ast_flags(node, AST_FLAG_PUBLIC))
+ return false;
+
+ if (same_src_scope(scope, node->scope))
+ return true;
+
+ return scope_flags(scope, SCOPE_PUBLIC);
+}
+
int scope_add_var(struct scope *scope, struct ast *var)
{
struct ast *exists = scope_find_symbol(scope, var_id(var));
@@ -176,8 +196,7 @@ int scope_add_var(struct scope *scope, struct ast *var)
}
create_var(scope, var_id(var), var);
- if (scope->parent &&
- scope_flags(scope, SCOPE_FILE) && ast_flags(var, AST_FLAG_PUBLIC))
+ if (scope_add_recurse(scope, var))
return scope_add_var(scope->parent, var);
return 0;
@@ -193,8 +212,7 @@ int scope_add_type(struct scope *scope, char *id, struct ast *type)
}
create_type(scope, id, type);
- if (scope->parent &&
- scope_flags(scope, SCOPE_FILE) && ast_flags(type, AST_FLAG_PUBLIC))
+ if (scope_add_recurse(scope, type))
return scope_add_type(scope->parent, id, type);
return 0;
@@ -251,8 +269,7 @@ int scope_add_chain(struct scope *scope, char *id, struct ast *type)
insert_chain(scope, id, type);
- if (scope->parent &&
- scope_flags(scope, SCOPE_FILE) && ast_flags(type, AST_FLAG_PUBLIC))
+ if (scope_add_recurse(scope, type))
return scope_add_chain(scope->parent, id, type);
return 0;
@@ -270,8 +287,7 @@ int scope_add_macro(struct scope *scope, struct ast *macro)
/* always add to scope, do resolve checking later */
create_macro(scope, macro_def_id(macro), macro);
- if (scope->parent &&
- scope_flags(scope, SCOPE_FILE) && ast_flags(macro, AST_FLAG_PUBLIC))
+ if (scope_add_recurse(scope, macro))
return scope_add_macro(scope->parent, macro);
return 0;
@@ -282,15 +298,14 @@ int scope_add_proc(struct scope *scope, struct ast *proc)
assert(proc->k == AST_PROC_DEF);
struct ast *exists = file_scope_find_symbol(scope, proc_id(proc));
if (exists) {
- semantic_error(scope->fctx, proc, "proc redefined");
- semantic_info(scope->fctx, exists, "previously here");
+ semantic_error(proc->scope->fctx, proc, "proc redefined");
+ semantic_info(exists->scope->fctx, exists, "previously here");
return -1;
}
/* always add to scope, do resolve checking later */
create_proc(scope, proc_id(proc), proc);
- if (scope->parent &&
- scope_flags(scope, SCOPE_FILE) && ast_flags(proc, AST_FLAG_PUBLIC))
+ if (scope_add_recurse(scope, proc))
return scope_add_proc(scope->parent, proc);
return 0;
@@ -309,8 +324,7 @@ int scope_add_trait(struct scope *scope, struct ast *trait)
}
create_type(scope, id, trait);
- if (scope->parent &&
- scope_flags(scope, SCOPE_FILE) && ast_flags(trait, AST_FLAG_PUBLIC))
+ if (scope_add_recurse(scope, trait))
return scope_add_trait(scope->parent, trait);
return 0;
@@ -324,8 +338,7 @@ int scope_add_expd_struct(struct scope *scope, struct ast *def,
assert(file_scope_find_expd_struct(scope, def, types) == NULL);
create_expanded(scope, def, types, expd);
- if (scope->parent &&
- scope_flags(scope, SCOPE_FILE) && ast_flags(def, AST_FLAG_PUBLIC))
+ if (scope_add_recurse(scope, expd))
return scope_add_expd_struct(scope->parent, def, types, expd);
return 0;
@@ -386,9 +399,8 @@ int scope_add_expd_chain(struct scope *scope, struct ast *def,
insert_expd_chain(scope, def, types, expd);
- if (scope->parent &&
- scope_flags(scope, SCOPE_FILE) && ast_flags(def, AST_FLAG_PUBLIC))
- return scope_add_expd_struct(scope->parent, def, types, expd);
+ if (scope_add_recurse(scope, expd))
+ return scope_add_expd_chain(scope->parent, def, types, expd);
return 0;
}
@@ -563,3 +575,9 @@ void scope_add_scope(struct scope *parent, struct scope *child)
child->next = parent->children;
parent->children = child;
}
+
+bool same_src(struct ast *a, struct ast *b)
+{
+ return same_src_scope(a->scope, b->scope);
+}
+