diff options
| -rw-r--r-- | include/ek/scope.h | 2 | ||||
| -rw-r--r-- | src/actualize.c | 32 | ||||
| -rw-r--r-- | src/ast.c | 2 | ||||
| -rw-r--r-- | src/scope.c | 58 | ||||
| -rw-r--r-- | tests/multiple_imports/a.ek | 3 | ||||
| -rw-r--r-- | tests/multiple_imports/b.ek | 3 | ||||
| -rw-r--r-- | tests/multiple_imports/common.ek | 1 | ||||
| -rw-r--r-- | tests/multiple_imports/multiple_imports.ek | 8 | ||||
| -rw-r--r-- | tests/multiple_imports/source.mk | 1 | ||||
| -rw-r--r-- | tests/struct_pub_generic_cont/source.mk | 1 | ||||
| -rw-r--r-- | tests/struct_pub_generic_cont/struct.ek | 14 | ||||
| -rw-r--r-- | tests/struct_pub_generic_cont/struct_pub_generic_cont.ek | 14 |
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; @@ -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(); +} |
