aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2025-01-11 16:30:39 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2025-01-11 16:30:39 +0200
commit45b3531e29c1b596f1be123de94b7c618c92bf8a (patch)
tree6fe6c326df6d8c8875a3ece1db17e9766030d579
parent47f1d503ec663f967302b3071177c40c431b3fdb (diff)
downloadek-45b3531e29c1b596f1be123de94b7c618c92bf8a.tar.gz
ek-45b3531e29c1b596f1be123de94b7c618c92bf8a.zip
multiple import stuff
-rw-r--r--include/ek/scope.h2
-rw-r--r--src/actualize.c32
-rw-r--r--src/ast.c2
-rw-r--r--src/scope.c58
-rw-r--r--tests/multiple_imports/a.ek3
-rw-r--r--tests/multiple_imports/b.ek3
-rw-r--r--tests/multiple_imports/common.ek1
-rw-r--r--tests/multiple_imports/multiple_imports.ek8
-rw-r--r--tests/multiple_imports/source.mk1
-rw-r--r--tests/struct_pub_generic_cont/source.mk1
-rw-r--r--tests/struct_pub_generic_cont/struct.ek14
-rw-r--r--tests/struct_pub_generic_cont/struct_pub_generic_cont.ek14
12 files changed, 116 insertions, 23 deletions
diff --git a/include/ek/scope.h b/include/ek/scope.h
index e4c706a..d63d2fc 100644
--- a/include/ek/scope.h
+++ b/include/ek/scope.h
@@ -355,6 +355,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);
+bool same_src(struct ast *a, struct ast *b);
+
#define foreach_visible(iter, init) \
for (struct visible *iter = init; iter; iter = iter->next)
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);
+}
+
diff --git a/tests/multiple_imports/a.ek b/tests/multiple_imports/a.ek
new file mode 100644
index 0000000..7231bd0
--- /dev/null
+++ b/tests/multiple_imports/a.ek
@@ -0,0 +1,3 @@
+import "common.ek"
+
+pub a(){}
diff --git a/tests/multiple_imports/b.ek b/tests/multiple_imports/b.ek
new file mode 100644
index 0000000..b5fb714
--- /dev/null
+++ b/tests/multiple_imports/b.ek
@@ -0,0 +1,3 @@
+import "common.ek"
+
+pub b(){}
diff --git a/tests/multiple_imports/common.ek b/tests/multiple_imports/common.ek
new file mode 100644
index 0000000..dfe91ad
--- /dev/null
+++ b/tests/multiple_imports/common.ek
@@ -0,0 +1 @@
+pub some_func(){}
diff --git a/tests/multiple_imports/multiple_imports.ek b/tests/multiple_imports/multiple_imports.ek
new file mode 100644
index 0000000..42f44b6
--- /dev/null
+++ b/tests/multiple_imports/multiple_imports.ek
@@ -0,0 +1,8 @@
+import "a.ek";
+import "b.ek"
+
+main()
+{
+ a();
+ b();
+}
diff --git a/tests/multiple_imports/source.mk b/tests/multiple_imports/source.mk
new file mode 100644
index 0000000..82400e7
--- /dev/null
+++ b/tests/multiple_imports/source.mk
@@ -0,0 +1 @@
+SIMPLE += multiple_imports
diff --git a/tests/struct_pub_generic_cont/source.mk b/tests/struct_pub_generic_cont/source.mk
new file mode 100644
index 0000000..824c042
--- /dev/null
+++ b/tests/struct_pub_generic_cont/source.mk
@@ -0,0 +1 @@
+SIMPLE += struct_pub_generic_cont
diff --git a/tests/struct_pub_generic_cont/struct.ek b/tests/struct_pub_generic_cont/struct.ek
new file mode 100644
index 0000000..85f1711
--- /dev/null
+++ b/tests/struct_pub_generic_cont/struct.ek
@@ -0,0 +1,14 @@
+pub define any[] {}
+pub typedef i27 {}
+pub typedef struct[any T] {}
+
+/* private definition of some function */
+continue struct[any T] {
+ do_something(){}
+}
+
+pub some_func()
+{
+ mut p = struct![i27]{};
+ p.do_something();
+}
diff --git a/tests/struct_pub_generic_cont/struct_pub_generic_cont.ek b/tests/struct_pub_generic_cont/struct_pub_generic_cont.ek
new file mode 100644
index 0000000..905bdf9
--- /dev/null
+++ b/tests/struct_pub_generic_cont/struct_pub_generic_cont.ek
@@ -0,0 +1,14 @@
+import "struct.ek"
+
+continue struct[any T] {
+ do_something(){}
+}
+
+main()
+{
+ mut p = struct![i27]{};
+ /* should be different from do_something() defined in struct.ek */
+ p.do_something();
+
+ some_func();
+}