From 818396b6f38e3b736315e54227e4759b0f53a959 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 15 Feb 2023 09:47:51 +0100 Subject: [PATCH] Updated module visibility import visibility. Fixes to @local --- lib/std/core/allocators/dynamic_arena.c3 | 2 +- lib/std/io/io_printf.c3 | 4 +- src/compiler/compiler.c | 3 +- src/compiler/compiler_internal.h | 8 +- src/compiler/context.c | 30 ++-- src/compiler/enums.h | 1 + src/compiler/llvm_codegen.c | 2 +- src/compiler/parse_global.c | 129 ++++++++++-------- src/compiler/parse_stmt.c | 4 +- src/compiler/parser_internal.h | 4 +- src/compiler/sema_decls.c | 23 +--- src/compiler/sema_name_resolution.c | 4 +- src/compiler/sema_passes.c | 12 +- src/compiler/semantic_analyser.c | 2 +- src/compiler/symtab.c | 1 + test/test_suite/define/test_at.c3 | 2 +- test/test_suite/define/test_at_alias.c3 | 2 +- .../macros/macro_import_res_private.c3t | 2 +- .../extending_with_visibility_fail_private.c3 | 2 +- test/test_suite/module/private_module.c3 | 2 +- .../visibility/no_shared_imports.c3t | 9 +- test/test_suite/visibility/private_import.c3 | 2 +- test/test_suite/visibility/private_import2.c3 | 27 ++++ test/test_suite/visibility/private_module.c3 | 17 --- test/test_suite/visibility/shared_module.c3t | 5 +- 25 files changed, 149 insertions(+), 150 deletions(-) create mode 100644 test/test_suite/visibility/private_import2.c3 delete mode 100644 test/test_suite/visibility/private_module.c3 diff --git a/lib/std/core/allocators/dynamic_arena.c3 b/lib/std/core/allocators/dynamic_arena.c3 index 9cd8d8de0..4b5ac6004 100644 --- a/lib/std/core/allocators/dynamic_arena.c3 +++ b/lib/std/core/allocators/dynamic_arena.c3 @@ -1,6 +1,6 @@ module std::core::mem::allocator; -struct DynamicArenaPage @local +struct DynamicArenaPage { void* memory; void* prev_arena; diff --git a/lib/std/io/io_printf.c3 b/lib/std/io/io_printf.c3 index a9122650a..f4790bc5c 100644 --- a/lib/std/io/io_printf.c3 +++ b/lib/std/io/io_printf.c3 @@ -496,8 +496,8 @@ fn usz! Formatter.vprintf(Formatter* this, String format, variant[] variants) return this.idx; } -typedef StringFunctionMap = HashMap @private; -typedef FormatterFunctionMap = HashMap @private; +typedef StringFunctionMap @private = HashMap; +typedef FormatterFunctionMap @private = HashMap; FormatterFunctionMap toformat_functions @private; StringFunctionMap tostring_functions @private; diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 81c09a9c9..fdfcbead8 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -858,7 +858,7 @@ Module *global_context_find_module(const char *name) return htable_get(&global_context.modules, (void *)name); } -Module *compiler_find_or_create_module(Path *module_name, const char **parameters, bool is_private) +Module *compiler_find_or_create_module(Path *module_name, const char **parameters) { Module *module = global_context_find_module(module_name->module); if (module) return module; @@ -870,7 +870,6 @@ Module *compiler_find_or_create_module(Path *module_name, const char **parameter module->stage = ANALYSIS_NOT_BEGUN; module->parameters = parameters; module->is_generic = vec_size(parameters) > 0; - module->is_private = is_private; htable_init(&module->symbols, 0x10000); htable_set(&global_context.modules, (void *)module_name->module, module); if (parameters) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index dd4787caa..059c3fcb0 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -397,7 +397,7 @@ typedef struct typedef struct { Path *path; - bool private; + bool import_private_as_public; Module *module; } ImportDecl; @@ -1484,7 +1484,6 @@ typedef struct Module_ bool is_c_library : 1; bool is_exported : 1; bool is_generic : 1; - bool is_private : 1; bool no_extprefix : 1; AnalysisStage stage : 6; @@ -1580,6 +1579,7 @@ struct CompilationUnit_ Decl **enums; Decl **attributes; Decl **faulttypes; + Visibility default_visibility; struct { // Not properly implemented @@ -2088,7 +2088,7 @@ void global_context_add_type(Type *type); void global_context_add_decl(Decl *type_decl); void global_context_add_generic_decl(Decl *decl); -Module *compiler_find_or_create_module(Path *module_name, const char **parameters, bool is_private); +Module *compiler_find_or_create_module(Path *module_name, const char **parameters); Module *global_context_find_module(const char *name); const char *get_object_extension(void); @@ -2098,7 +2098,7 @@ void unit_register_external_symbol(CompilationUnit *unit, Decl *decl); bool unit_add_import(CompilationUnit *unit, Path *path, bool private_import); bool context_set_module_from_filename(ParseContext *context); -bool context_set_module(ParseContext *context, Path *path, const char **generic_parameters, bool is_private); +bool context_set_module(ParseContext *context, Path *path, const char **generic_parameters); // --- Decl functions diff --git a/src/compiler/context.c b/src/compiler/context.c index c24076328..d1739c7ef 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -14,12 +14,12 @@ CompilationUnit *unit_create(File *file) } -static inline bool create_module_or_check_name(CompilationUnit *unit, Path *module_name, const char **parameters, bool is_private) +static inline bool create_module_or_check_name(CompilationUnit *unit, Path *module_name, const char **parameters) { Module *module = unit->module; if (!module) { - module = unit->module = compiler_find_or_create_module(module_name, parameters, is_private); + module = unit->module = compiler_find_or_create_module(module_name, parameters); } else { @@ -33,19 +33,6 @@ static inline bool create_module_or_check_name(CompilationUnit *unit, Path *modu } } - if (module->is_private != is_private) - { - if (is_private) - { - SEMA_ERROR(module_name, "The module is declared as private here, but was declared as public elsewhere."); - } - else - { - SEMA_ERROR(module_name, "The module is declared as public here, but was declared as private elsewhere."); - } - return false; - - } vec_add(module->units, unit); return true; } @@ -104,10 +91,10 @@ bool context_set_module_from_filename(ParseContext *context) path->span = INVALID_SPAN; path->module = module_name; path->len = scratch_buffer.len; - return create_module_or_check_name(context->unit, path, NULL, true); + return create_module_or_check_name(context->unit, path, NULL); } -bool context_set_module(ParseContext *context, Path *path, const char **generic_parameters, bool is_private) +bool context_set_module(ParseContext *context, Path *path, const char **generic_parameters) { // Note that we allow the illegal name for now, to be able to parse further. if (!str_has_no_uppercase(path->module)) @@ -116,7 +103,7 @@ bool context_set_module(ParseContext *context, Path *path, const char **generic_ return false; } - return create_module_or_check_name(context->unit, path, generic_parameters, is_private); + return create_module_or_check_name(context->unit, path, generic_parameters); } @@ -283,7 +270,10 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl) Decl *old; if ((old = htable_set(&unit->local_symbols, (void*)decl->name, decl))) goto ERR; - if ((old = htable_set(&unit->module->symbols, (void*)decl->name, decl))) goto ERR; + if (decl->visibility < VISIBLE_LOCAL) + { + if ((old = htable_set(&unit->module->symbols, (void*)decl->name, decl))) goto ERR; + } return; ERR: assert(decl != old); @@ -306,7 +296,7 @@ bool unit_add_import(CompilationUnit *unit, Path *path, bool private_import) import->span = path->span; import->decl_kind = DECL_IMPORT; import->import.path = path; - import->import.private = private_import; + import->import.import_private_as_public = private_import; vec_add(unit->imports, import); DEBUG_LOG("Added import %s", path->module); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 5aa3f1aec..8a61f1f64 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -782,6 +782,7 @@ typedef enum ATTRIBUTE_PACKED, ATTRIBUTE_PRIORITY, ATTRIBUTE_PRIVATE, + ATTRIBUTE_PUBLIC, ATTRIBUTE_PURE, ATTRIBUTE_REFLECT, ATTRIBUTE_SECTION, diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 86538039f..9bfacf9e9 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -1123,7 +1123,7 @@ static void llvm_gen_test_main(GenContext *c) INLINE GenContext *llvm_gen_tests(Module** modules, unsigned module_count, LLVMContextRef shared_context) { Path *test_path = path_create_from_string("$test", 5, INVALID_SPAN); - Module *test_module = compiler_find_or_create_module(test_path, NULL, false); + Module *test_module = compiler_find_or_create_module(test_path, NULL); GenContext *c = cmalloc(sizeof(GenContext)); active_target.debug_info = DEBUG_INFO_NONE; diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 7deaf2937..f112ea68f 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -2,11 +2,12 @@ #include "parser_internal.h" -static Decl *parse_const_declaration(ParseContext *c); +static Decl *parse_const_declaration(ParseContext *c, bool is_global); static inline Decl *parse_func_definition(ParseContext *c, AstId docs, bool is_interface); static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl); static inline Decl *parse_static_top_level(ParseContext *c); static Decl *parse_include(ParseContext *c); +static bool parse_attributes_for_global(ParseContext *c, Decl *decl); #define DECL_VAR_NEW(type__, var__) decl_new_var(symstr(c), c->span, type__, var__); @@ -310,12 +311,10 @@ static inline bool parse_optional_module_params(ParseContext *c, const char ***t } /** - * module ::= MODULE module_path ('<' module_params '>')? EOS + * module ::= MODULE module_path ('<' module_params '>')? (@public|@private|@local)? EOS */ bool parse_module(ParseContext *c, AstId docs) { - bool is_private = try_consume(c, TOKEN_PRIVATE); - if (tok_is(c, TOKEN_STRING)) { SEMA_ERROR_HERE("'module' should be followed by a plain identifier, not a string. Did you accidentally put the module name between \"\"?"); @@ -348,7 +347,7 @@ bool parse_module(ParseContext *c, AstId docs) path->len = (unsigned)strlen("#invalid"); path->module = "#invalid"; path->span = INVALID_SPAN; - context_set_module(c, path, NULL, false); + context_set_module(c, path, NULL); recover_top_level(c); return false; } @@ -357,7 +356,7 @@ bool parse_module(ParseContext *c, AstId docs) const char **generic_parameters = NULL; if (!parse_optional_module_params(c, &generic_parameters)) { - if (!context_set_module(c, path, NULL, is_private)) return false; + if (!context_set_module(c, path, NULL)) return false; recover_top_level(c); if (docs) { @@ -366,7 +365,7 @@ bool parse_module(ParseContext *c, AstId docs) } return true; } - if (!context_set_module(c, path, generic_parameters, is_private)) return false; + if (!context_set_module(c, path, generic_parameters)) return false; if (docs) { AstId old_docs = c->unit->module->docs; @@ -380,7 +379,15 @@ bool parse_module(ParseContext *c, AstId docs) c->unit->module->docs = docs; } } - + Visibility visibility = VISIBLE_PUBLIC; + Attr** attrs = NULL; + if (!parse_attributes(c, &attrs, &visibility)) return false; + if (attrs) + { + sema_error_at(attrs[0]->span, "Unexpected '%s' after module name - only @public, @private and @local is permitted here.", attrs[0]->name); + return false; + } + c->unit->default_visibility = visibility; CONSUME_EOS_OR_RET(false); return true; } @@ -779,7 +786,7 @@ TypeInfo *parse_optional_type(ParseContext *c) * @param type * @return */ -Decl *parse_decl_after_type(ParseContext *c, TypeInfo *type) +Decl *parse_local_decl_after_type(ParseContext *c, TypeInfo *type) { if (tok_is(c, TOKEN_LPAREN)) { @@ -803,7 +810,7 @@ Decl *parse_decl_after_type(ParseContext *c, TypeInfo *type) Decl *decl = DECL_VAR_NEW(type, VARDECL_LOCAL); advance(c); - if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL)) return poisoned_decl; if (tok_is(c, TOKEN_EQ)) { if (!decl) @@ -826,7 +833,7 @@ Decl *parse_local_decl(ParseContext *c) { if (tok_is(c, TOKEN_CONST)) { - ASSIGN_DECL_OR_RET(Decl *decl, parse_const_declaration(c), poisoned_decl); + ASSIGN_DECL_OR_RET(Decl *decl, parse_const_declaration(c, false), poisoned_decl); decl->visibility = VISIBLE_LOCAL; return decl; } @@ -836,7 +843,7 @@ Decl *parse_local_decl(ParseContext *c) ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), poisoned_decl); - ASSIGN_DECL_OR_RET(Decl * decl, parse_decl_after_type(c, type), poisoned_decl); + ASSIGN_DECL_OR_RET(Decl * decl, parse_local_decl_after_type(c, type), poisoned_decl); if (type->optional && decl->var.unwrap) { SEMA_ERROR(decl, "You cannot use unwrap with an optional variable."); @@ -858,7 +865,7 @@ Expr *parse_decl_or_expr(ParseContext *c, Decl **decl_ref) TypeInfo *type_info; Expr *expr = parse_expr(c); if (expr->expr_kind != EXPR_TYPEINFO) return expr; - ASSIGN_DECL_OR_RET(*decl_ref, parse_decl_after_type(c, expr->type_expr), poisoned_expr); + ASSIGN_DECL_OR_RET(*decl_ref, parse_local_decl_after_type(c, expr->type_expr), poisoned_expr); return NULL; } @@ -868,7 +875,7 @@ Expr *parse_decl_or_expr(ParseContext *c, Decl **decl_ref) * : 'const' type? IDENT '=' const_expr * ; */ -static Decl *parse_const_declaration(ParseContext *c) +static Decl *parse_const_declaration(ParseContext *c, bool is_global) { advance_and_verify(c, TOKEN_CONST); @@ -882,7 +889,9 @@ static Decl *parse_const_declaration(ParseContext *c) if (!consume_const_name(c, "const")) return poisoned_decl; - if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; + Visibility visibility = is_global ? c->unit->default_visibility : VISIBLE_LOCAL; + if (!parse_attributes(c, &decl->attributes, is_global ? &visibility : NULL)) return poisoned_decl; + decl->visibility = visibility; CONSUME_OR_RET(TOKEN_EQ, poisoned_decl); @@ -1020,6 +1029,15 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref) *attribute_ref = attr; return true; } + +static bool parse_attributes_for_global(ParseContext *c, Decl *decl) +{ + Visibility visibility = c->unit->default_visibility; + if (!parse_attributes(c, &decl->attributes, &visibility)) return false; + decl->visibility = visibility; + return true; +} + /** * attribute_list * : attribute @@ -1031,42 +1049,41 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref) * * @return true if parsing succeeded, false if recovery is needed */ -bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Decl *owner) +bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref) { + Visibility visibility = -1; while (1) { Attr *attr; if (!parse_attribute(c, &attr)) return false; if (!attr) return true; const char *name = attr->name; + Visibility parsed_visibility = -1; if (name == attribute_list[ATTRIBUTE_PRIVATE]) { - if (!owner) - { - SEMA_ERROR(attr, "'%s' cannot be used here."); - return false; - } - if (owner->visibility != VISIBLE_PUBLIC) - { - SEMA_ERROR(attr, "Only a single visibility attribute may be added."); - return false; - } - owner->visibility = VISIBLE_PRIVATE; - continue; + parsed_visibility = VISIBLE_PRIVATE; } - if (name == attribute_list[ATTRIBUTE_LOCAL]) + else if (name == attribute_list[ATTRIBUTE_PUBLIC]) { - if (!owner) + parsed_visibility = VISIBLE_PUBLIC; + } + else if (name == attribute_list[ATTRIBUTE_LOCAL]) + { + parsed_visibility = VISIBLE_LOCAL; + } + if (parsed_visibility != -1) + { + if (!visibility_ref) { SEMA_ERROR(attr, "'%s' cannot be used here."); return false; } - if (owner->visibility != VISIBLE_PUBLIC) + if (visibility != -1) { SEMA_ERROR(attr, "Only a single visibility attribute may be added."); return false; } - owner->visibility = VISIBLE_LOCAL; + *visibility_ref = visibility = parsed_visibility; continue; } FOREACH_BEGIN(Attr *other_attr, *attributes_ref) @@ -1127,7 +1144,8 @@ static inline Decl *parse_global_declaration(ParseContext *c) // Add the last, or we miss it. if (decls) vec_add(decls, decl); - if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; + if (!parse_attributes_for_global(c, decl)) return poisoned_decl; + if (try_consume(c, TOKEN_EQ)) { if (decls) @@ -1607,10 +1625,7 @@ static inline Decl *parse_struct_declaration(ParseContext *c) if (!consume_type_name(c, type_name)) return poisoned_decl; - if (!parse_attributes(c, &decl->attributes, decl)) - { - return poisoned_decl; - } + if (!parse_attributes_for_global(c, decl)) return poisoned_decl; if (!parse_struct_body(c, decl)) { @@ -1676,15 +1691,9 @@ static inline Decl *parse_bitstruct_declaration(ParseContext *c) ASSIGN_TYPE_OR_RET(decl->bitstruct.base_type, parse_type(c), poisoned_decl); - if (!parse_attributes(c, &decl->attributes, decl)) - { - return poisoned_decl; - } + if (!parse_attributes_for_global(c, decl)) return poisoned_decl; - if (!parse_bitstruct_body(c, decl)) - { - return poisoned_decl; - } + if (!parse_bitstruct_body(c, decl)) return poisoned_decl; return decl; @@ -1692,7 +1701,7 @@ static inline Decl *parse_bitstruct_declaration(ParseContext *c) static inline Decl *parse_top_level_const_declaration(ParseContext *c) { - ASSIGN_DECL_OR_RET(Decl * decl, parse_const_declaration(c), poisoned_decl); + ASSIGN_DECL_OR_RET(Decl * decl, parse_const_declaration(c, true), poisoned_decl); CONSUME_EOS_OR_RET(poisoned_decl); return decl; } @@ -1792,7 +1801,9 @@ static inline Decl *parse_define_type(ParseContext *c) SEMA_ERROR_HERE("A type name was expected here."); return poisoned_decl; } - if (!parse_attributes(c, &decl->attributes, decl)) return false; + + if (!parse_attributes_for_global(c, decl)) return poisoned_decl; + CONSUME_OR_RET(TOKEN_EQ, poisoned_decl); bool distinct = false; if (tok_is(c, TOKEN_IDENT) && symstr(c) == kw_distinct) @@ -1833,7 +1844,6 @@ static inline Decl *parse_define_type(ParseContext *c) decl->define_decl.type_info = type_info; decl->define_decl.generic_params = params; RANGE_EXTEND_PREV(decl); - if (!parse_attributes(c, &decl->attributes, decl)) return false; CONSUME_EOS_OR_RET(poisoned_decl); return decl; } @@ -1985,8 +1995,9 @@ static inline Decl *parse_define_attribute(ParseContext *c) CONSUME_OR_RET(TOKEN_RPAREN, poisoned_decl); } + if (!parse_attributes_for_global(c, decl)) return poisoned_decl; Attr **attributes = NULL; - if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; + CONSUME_OR_RET(TOKEN_EQ, poisoned_decl); CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl); @@ -2104,7 +2115,7 @@ static inline Decl *parse_macro_declaration(ParseContext *c, AstId docs) const char *block_parameter = NULL; if (!parse_macro_arguments(c, decl)) return poisoned_decl; - if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; + if (!parse_attributes_for_global(c, decl)) return poisoned_decl; if (tok_is(c, TOKEN_IMPLIES)) { ASSIGN_ASTID_OR_RET(decl->func_decl.body, @@ -2235,7 +2246,8 @@ static inline Decl *parse_enum_declaration(ParseContext *c, bool is_private) if (!parse_enum_spec(c, &type, &decl->enums.parameters)) return poisoned_decl; } - if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; + if (!parse_attributes_for_global(c, decl)) return poisoned_decl; + Visibility visibility = decl->visibility; CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl); @@ -2315,7 +2327,7 @@ static inline Decl *parse_func_definition(ParseContext *c, AstId docs, bool is_i return false; } if (!parse_fn_parameter_list(c, &(func->func_decl.signature), is_interface)) return poisoned_decl; - if (!parse_attributes(c, &func->attributes, func)) return poisoned_decl; + if (!parse_attributes_for_global(c, func)) return poisoned_decl; // TODO remove is_interface = tok_is(c, TOKEN_EOS); @@ -2404,8 +2416,6 @@ static inline bool parse_import(ParseContext *c) { advance_and_verify(c, TOKEN_IMPORT); - bool private = try_consume(c, TOKEN_PRIVATE); - bool is_not_first = false; while (1) { @@ -2427,6 +2437,17 @@ static inline bool parse_import(ParseContext *c) is_not_first = true; Path *path = parse_module_path(c); if (!path) return false; + bool private = false; + if (tok_is(c, TOKEN_AT_IDENT)) + { + if (symstr(c) != attribute_list[ATTRIBUTE_PUBLIC]) + { + SEMA_ERROR_HERE("Only '@public' is a valid attribute here."); + return false; + } + private = true; + advance_and_verify(c, TOKEN_AT_IDENT); + } unit_add_import(c->unit, path, private); if (tok_is(c, TOKEN_COLON) && peek(c) == TOKEN_IDENT) { diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index ffbbe319c..edf23e2bd 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -15,7 +15,7 @@ static Ast *parse_declaration_statment_after_type(ParseContext *c, TypeInfo *typ Ast *ast = ast_calloc(); ast->span = type->span; ast->ast_kind = AST_DECLARE_STMT; - ASSIGN_DECL_OR_RET(ast->declare_stmt, parse_decl_after_type(c, type), poisoned_ast); + ASSIGN_DECL_OR_RET(ast->declare_stmt, parse_local_decl_after_type(c, type), poisoned_ast); if (tok_is(c, TOKEN_EOS)) return ast; Decl *decl = ast->declare_stmt; @@ -43,7 +43,7 @@ static Ast *parse_declaration_statment_after_type(ParseContext *c, TypeInfo *typ Attr **attributes = NULL; while (try_consume(c, TOKEN_COMMA)) { - ASSIGN_DECL_OR_RET(decl, parse_decl_after_type(c, copy_type_info_single(type)), poisoned_ast); + ASSIGN_DECL_OR_RET(decl, parse_local_decl_after_type(c, copy_type_info_single(type)), poisoned_ast); if (decl->var.init_expr) { SEMA_ERROR(decl->var.init_expr, "Multiple variable declarations cannot use initialization."); diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index ca0b0607c..848da6f19 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -48,12 +48,12 @@ Ast* parse_compound_stmt(ParseContext *c); Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool require_eos); Ast *parse_jump_stmt_no_eos(ParseContext *c); bool parse_attribute(ParseContext *c, Attr **attribute_ref); -bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Decl *owner); +bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility); bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type); Expr *parse_ct_expression_list(ParseContext *c, bool allow_decl); Expr *parse_expression_list(ParseContext *c, bool allow_decls); -Decl *parse_decl_after_type(ParseContext *c, TypeInfo *type); +Decl *parse_local_decl_after_type(ParseContext *c, TypeInfo *type); Decl *parse_var_decl(ParseContext *c); bool parse_parameters(ParseContext *c, Decl ***params_ref, Decl **body_params, diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index b971ade0a..c8b85db9b 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1502,6 +1502,11 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, Expr *expr = args ? attr->exprs[0] : NULL; switch (type) { + case ATTRIBUTE_PRIVATE: + case ATTRIBUTE_PUBLIC: + case ATTRIBUTE_LOCAL: + // These are pseudo-attributes. + UNREACHABLE; case ATTRIBUTE_WINMAIN: if (decl->name != kw_main) { @@ -1531,22 +1536,6 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, break; } break; - case ATTRIBUTE_PRIVATE: - if (decl->visibility != VISIBLE_PUBLIC) - { - SEMA_ERROR(decl, "Multiple visibility attributes cannot be combined."); - return false; - } - decl->visibility = VISIBLE_PRIVATE; - break; - case ATTRIBUTE_LOCAL: - if (decl->visibility != VISIBLE_PUBLIC) - { - SEMA_ERROR(decl, "Multiple visibility attributes cannot be combined."); - return false; - } - decl->visibility = VISIBLE_LOCAL; - break; case ATTRIBUTE_TEST: decl->func_decl.attr_test = true; break; @@ -2764,7 +2753,7 @@ static CompilationUnit *unit_copy(Module *module, CompilationUnit *unit) static Module *module_instantiate_generic(Module *module, Path *path, Expr **params) { - Module *new_module = compiler_find_or_create_module(path, NULL, module->is_private); + Module *new_module = compiler_find_or_create_module(path, NULL); new_module->is_generic = false; CompilationUnit **units = module->units; VECEACH(units, i) diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index d5eb53616..d007b41d3 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -153,7 +153,7 @@ static Decl *sema_find_decl_in_imports(Decl **imports, NameResolve *name_resolve assert(found->visibility != VISIBLE_LOCAL); // If we found something private but we don't import privately? - if (found->visibility == VISIBLE_PRIVATE && !import->import.private && !decl) + if (found->visibility == VISIBLE_PRIVATE && !import->import.import_private_as_public && !decl) { // Register this as a possible private decl. name_resolve->private_decl = found; @@ -704,7 +704,7 @@ Decl *sema_resolve_type_method(CompilationUnit *unit, Type *type, const char *me Decl *new_found = sema_resolve_method_in_module(import->import.module, type, method_name, &private, &ambiguous, - import->import.private + import->import.import_private_as_public ? METHOD_SEARCH_PRIVATE_IMPORTED : METHOD_SEARCH_IMPORTED); if (!new_found) continue; diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index 2d71a1c4c..002bf44d6 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -52,7 +52,7 @@ void sema_analyse_pass_module_hierarchy(Module *module) // No match, so we create a synthetic module. Path *path = path_create_from_string(slice.ptr, slice.len, module->name->span); DEBUG_LOG("Creating parent module for %s: %s", module->name->module, path->module); - Module *parent_module = compiler_find_or_create_module(path, NULL, false /* always public */); + Module *parent_module = compiler_find_or_create_module(path, NULL); module->parent_module = parent_module; vec_add(parent_module->sub_modules, module); sema_analyze_stage(parent_module, ANALYSIS_MODULE_HIERARCHY); @@ -100,15 +100,7 @@ void sema_analysis_pass_process_imports(Module *module) continue; } - // 7. Importing private is not allowed. - if (import_module->is_private && !import->import.private) - { - SEMA_ERROR(import, "Importing a private module is not allowed (unless 'import private' is used)."); - decl_poison(import); - continue; - } - - // 8. Assign the module. + // 7. Assign the module. DEBUG_LOG("* Import of %s.", path->module); import->import.module = import_module; } diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 77cff493d..9b2ccc2ac 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -294,7 +294,7 @@ void sema_analysis_run(void) core_path->module = kw_std__core; core_path->span = INVALID_SPAN; core_path->len = strlen(kw_std__core); - global_context.core_module = compiler_find_or_create_module(core_path, NULL, false); + global_context.core_module = compiler_find_or_create_module(core_path, NULL); // We parse the generic modules, just by storing the decls. FOREACH_BEGIN(Module *module, global_context.generic_module_list) diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 98811babf..11e104822 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -315,6 +315,7 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_PRIORITY] = KW_DEF("@priority"); attribute_list[ATTRIBUTE_PRIVATE] = KW_DEF("@private"); attribute_list[ATTRIBUTE_PURE] = kw_at_pure; + attribute_list[ATTRIBUTE_PUBLIC] = KW_DEF("@public"); attribute_list[ATTRIBUTE_REFLECT] = KW_DEF("@reflect"); attribute_list[ATTRIBUTE_SECTION] = KW_DEF("@section"); attribute_list[ATTRIBUTE_STDCALL] = KW_DEF("@stdcall"); diff --git a/test/test_suite/define/test_at.c3 b/test/test_suite/define/test_at.c3 index 30c060010..621b2871a 100644 --- a/test/test_suite/define/test_at.c3 +++ b/test/test_suite/define/test_at.c3 @@ -7,7 +7,7 @@ macro @hello(Type thing) { module bar; -import private foo; +import foo @public; define intHello = foo::@hello; // #error: cannot be aliased define @intHello = foo::hello; // #error: cannot use diff --git a/test/test_suite/define/test_at_alias.c3 b/test/test_suite/define/test_at_alias.c3 index f10964a90..612b6dadf 100644 --- a/test/test_suite/define/test_at_alias.c3 +++ b/test/test_suite/define/test_at_alias.c3 @@ -7,7 +7,7 @@ macro @hello(Type thing) { module bar; -import private foo; +import foo @public; define @intHello = foo::@hello; diff --git a/test/test_suite/macros/macro_import_res_private.c3t b/test/test_suite/macros/macro_import_res_private.c3t index 377fe02fe..410d28e5d 100644 --- a/test/test_suite/macros/macro_import_res_private.c3t +++ b/test/test_suite/macros/macro_import_res_private.c3t @@ -4,7 +4,7 @@ fn void foo1() @private {} module bar; -import private foo; +import foo @public; macro bar1() { foo::foo1(); diff --git a/test/test_suite/methods/extending_with_visibility_fail_private.c3 b/test/test_suite/methods/extending_with_visibility_fail_private.c3 index 3e8bb5ffe..89b169507 100644 --- a/test/test_suite/methods/extending_with_visibility_fail_private.c3 +++ b/test/test_suite/methods/extending_with_visibility_fail_private.c3 @@ -15,7 +15,7 @@ fn int Bar.get2(Bar* f) => f.x; fn int Bar.get3(Bar* f) @local => f.x; module abc; -import private test; +import test @public; struct Bar { diff --git a/test/test_suite/module/private_module.c3 b/test/test_suite/module/private_module.c3 index b29de1f17..837e36b94 100644 --- a/test/test_suite/module/private_module.c3 +++ b/test/test_suite/module/private_module.c3 @@ -1 +1 @@ -module private foo; \ No newline at end of file +module foo @private; \ No newline at end of file diff --git a/test/test_suite/visibility/no_shared_imports.c3t b/test/test_suite/visibility/no_shared_imports.c3t index 28c0e8e42..3555ee02c 100644 --- a/test/test_suite/visibility/no_shared_imports.c3t +++ b/test/test_suite/visibility/no_shared_imports.c3t @@ -9,15 +9,14 @@ fn void runBar() // #file: file2.c3 module baz; -import private bar; +import bar @public; -fn void visible() - @private{ +fn void visible() @private +{ bar::barFunc(); } // #file: file3.c3 module bar; -fn void barFunc() - @private{} \ No newline at end of file +fn void barFunc() @private {} \ No newline at end of file diff --git a/test/test_suite/visibility/private_import.c3 b/test/test_suite/visibility/private_import.c3 index 2e23b9a65..ea8421d1e 100644 --- a/test/test_suite/visibility/private_import.c3 +++ b/test/test_suite/visibility/private_import.c3 @@ -13,7 +13,7 @@ fn void test() } module baz; -import private foo; +import foo @public; fn void test() { diff --git a/test/test_suite/visibility/private_import2.c3 b/test/test_suite/visibility/private_import2.c3 new file mode 100644 index 000000000..fc9097f1b --- /dev/null +++ b/test/test_suite/visibility/private_import2.c3 @@ -0,0 +1,27 @@ +module test; + +fn void bar() @private +{ +} +fn void bar2() @local +{ +} + +module baz; +import test @public; + +fn void abc() +{ + test::bar(); + test::bar2(); // #error: could not be found +} + +module baz2; + +import test; + +fn void abc() +{ + test::bar(); // #error: not visible + test::bar2(); // #error: could not be found +} \ No newline at end of file diff --git a/test/test_suite/visibility/private_module.c3 b/test/test_suite/visibility/private_module.c3 deleted file mode 100644 index 5faba9b0b..000000000 --- a/test/test_suite/visibility/private_module.c3 +++ /dev/null @@ -1,17 +0,0 @@ -module private foo; - -fn void hidden() -{ -} - -module bar; -import foo; // #error: Importing a private module is not allowed (unless 'import private' is used). - - -module baz; -import private foo; - -fn void test() -{ - foo::hidden(); -} \ No newline at end of file diff --git a/test/test_suite/visibility/shared_module.c3t b/test/test_suite/visibility/shared_module.c3t index dc1adad95..34daced46 100644 --- a/test/test_suite/visibility/shared_module.c3t +++ b/test/test_suite/visibility/shared_module.c3t @@ -9,7 +9,4 @@ fn void runBar() // #file: file2.c3 module baz; -fn void visible() - @private{ - -} \ No newline at end of file +fn void visible() @private {} \ No newline at end of file