From 5e457be605ed293e2a982ee9a8cebeade8044a53 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 13 Feb 2023 08:31:40 +0100 Subject: [PATCH] =?UTF-8?q?Implement=20more=20@export=20/=20@private=20imp?= =?UTF-8?q?rovements.=20Make=20@private=20default=E2=80=A6=20(#729)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/main.yml | 4 +- lib/std/collections/enumset.c3 | 12 +- lib/std/collections/linkedlist.c3 | 18 +- lib/std/collections/list.c3 | 2 +- lib/std/collections/map.c3 | 37 +- lib/std/core/allocators/arena_allocator.c3 | 6 +- lib/std/core/allocators/dynamic_arena.c3 | 16 +- lib/std/core/allocators/heap_allocator.c3 | 12 +- lib/std/core/allocators/mem_allocator_fn.c3 | 6 +- lib/std/core/allocators/temp_allocator.c3 | 18 +- lib/std/core/conv.c3 | 16 +- lib/std/core/floatparse.c3 | 2 +- lib/std/core/mem.c3 | 7 +- lib/std/core/mem_allocator.c3 | 2 +- lib/std/core/private/main_stub.c3 | 10 +- lib/std/core/runtime.c3 | 2 +- lib/std/core/str.c3 | 18 +- lib/std/core/string.c3 | 19 +- lib/std/hash/adler32.c3 | 2 +- lib/std/hash/crc32.c3 | 2 +- lib/std/hash/crc64.c3 | 2 +- lib/std/hash/fnv32a.c3 | 6 +- lib/std/io/dir.c3 | 6 +- lib/std/io/io_fileinfo.c3 | 4 +- lib/std/io/io_formatter_private.c3 | 34 +- lib/std/io/io_printf.c3 | 166 ++++----- lib/std/math/math.c3 | 8 +- lib/std/math/math.matrix.c3 | 6 +- lib/std/math/math.simple_random.c3 | 10 +- lib/std/math/math_easings.c3 | 4 +- lib/std/math/math_i128.c3 | 12 +- lib/std/math/math_nolibc/__cosdf.c3 | 8 +- lib/std/math/math_nolibc/atan.c3 | 20 +- lib/std/math/math_nolibc/exp2.c3 | 6 +- lib/std/math/math_nolibc/math_nolibc.c3 | 18 +- lib/std/math/math_vector.c3 | 30 +- lib/std/os/win32/files.c3 | 12 +- lib/std/threads/os/thread_posix.c3 | 4 +- lib/std/threads/os/thread_win32.c3 | 2 +- resources/examples/contextfree/boolerr.c3 | 2 +- resources/examples/fasta.c3 | 2 +- resources/examples/hash.c3 | 4 +- .../examples/notworking/acornvm/avm_array.c3 | 2 +- .../examples/notworking/acornvm/lexer.c3 | 2 +- resources/testproject/foo.c3 | 4 +- src/compiler/ast.c | 13 +- src/compiler/compiler_internal.h | 14 +- src/compiler/context.c | 3 +- src/compiler/enums.h | 2 + src/compiler/llvm_codegen.c | 74 ++-- src/compiler/llvm_codegen_debug_info.c | 23 +- src/compiler/llvm_codegen_function.c | 47 +-- src/compiler/parse_expr.c | 8 +- src/compiler/parse_global.c | 340 +++++++++++------- src/compiler/parse_stmt.c | 12 +- src/compiler/parser_internal.h | 6 +- src/compiler/sema_casts.c | 6 + src/compiler/sema_decls.c | 36 +- src/compiler/sema_name_resolution.c | 4 +- src/compiler/sema_passes.c | 2 +- src/compiler/sema_stmts.c | 12 +- src/compiler/semantic_analyser.c | 2 +- src/compiler/symtab.c | 1 + src/version.h | 2 +- test/test_suite/arrays/array_struct.c3t | 2 +- .../test_suite/arrays/complex_array_const.c3t | 2 +- .../attributes/attribute_visibility.c3t | 6 +- .../attributes/recursive_attributes.c3 | 6 +- .../attributes/user_defined_attributes.c3t | 10 +- test/test_suite/clang/2002-07.c3t | 8 +- test/test_suite/constants/constants.c3t | 18 +- test/test_suite/debug_symbols/constants.c3t | 6 +- .../expressions/bool_conversions.c3t | 2 +- .../test_suite/import/access_other_module.c3t | 2 +- test/test_suite/initializer_lists/fasta.c3t | 2 +- test/test_suite/lambda/nested_lambda_def.c3t | 2 +- test/test_suite/macros/hash_ident.c3 | 2 +- .../macros/macro_import_res_private.c3t | 2 +- test/test_suite/macros/macro_resolution.c3 | 2 +- test/test_suite/pointers/const_pointer.c3t | 8 +- test/test_suite/struct/simple_struct.c3t | 2 +- .../struct/struct_const_construct_simple.c3t | 18 +- test/test_suite/union/union_codegen_const.c3t | 7 +- test/test_suite/visibility/ambiguous_var.c3t | 4 +- .../visibility/no_shared_imports.c3t | 8 +- test/test_suite/visibility/not_visible.c3t | 4 +- test/test_suite/visibility/private_import.c3 | 2 +- test/test_suite/visibility/shared_module.c3t | 4 +- 88 files changed, 697 insertions(+), 624 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 991a2c247..0ac66776f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -267,8 +267,8 @@ jobs: - uses: actions/checkout@v3 - name: Download LLVM run: | - brew update && brew install --overwrite python && brew install python-tk - brew install llvm@${{ matrix.llvm_version }} botan ninja curl + brew update + brew install llvm@${{ matrix.llvm_version }} ninja curl echo "/usr/local/opt/llvm@${{ matrix.llvm_version }}/bin" >> $GITHUB_PATH TMP_PATH=$(xcrun --show-sdk-path)/user/include echo "CPATH=$TMP_PATH" >> $GITHUB_ENV diff --git a/lib/std/collections/enumset.c3 b/lib/std/collections/enumset.c3 index ec12f6a78..f7eb08080 100644 --- a/lib/std/collections/enumset.c3 +++ b/lib/std/collections/enumset.c3 @@ -5,20 +5,20 @@ $assert(Enum.elements < 64, "Maximum number of elements for an enum used as enum $switch ($$C_INT_SIZE): $case 64: - private define EnumSetType = ulong; + define EnumSetType @private = ulong; $case 32: $if (Enum.elements < 32): - private define EnumSetType = uint; + define EnumSetType @private = uint; $else: - private define EnumSetType = ulong; + define EnumSetType @private = ulong; $endif; $default: $if (Enum.elements < 16): - private define EnumSetType = ushort; + define EnumSetType @private = ushort; $elif (Enum.elements < 31): - private define EnumSetType = uint; + define EnumSetType @private = uint; $else: - private define EnumSetType = ulong; + define EnumSetType @private = ulong; $endif; $endswitch; diff --git a/lib/std/collections/linkedlist.c3 b/lib/std/collections/linkedlist.c3 index 563ae4d79..a0ecee378 100644 --- a/lib/std/collections/linkedlist.c3 +++ b/lib/std/collections/linkedlist.c3 @@ -3,7 +3,7 @@ // a copy of which can be found in the LICENSE_STDLIB file. module std::collections::linkedlist; -private struct Node +struct Node @private { Node *next; Node *prev; @@ -38,17 +38,17 @@ fn void LinkedList.tinit(LinkedList* list) => list.init(mem::temp_allocator()) @ /** * @require list.allocator **/ -private macro void LinkedList.@free_node(LinkedList &list, Node* node) +macro void LinkedList.@free_node(LinkedList &list, Node* node) @private { list.allocator.free(node)!!; } -private macro Node* LinkedList.@alloc_node(LinkedList &list) +macro Node* LinkedList.@alloc_node(LinkedList &list) @private { if (!list.allocator) list.allocator = mem::current_allocator(); return list.allocator.alloc(Node.sizeof)!!; } -private fn void LinkedList.link_first(LinkedList* list, Type value) +fn void LinkedList.link_first(LinkedList* list, Type value) @private { Node *first = list._first; Node *new_node = list.@alloc_node(); @@ -65,7 +65,7 @@ private fn void LinkedList.link_first(LinkedList* list, Type value) list.size++; } -private fn void LinkedList.link_last(LinkedList* list, Type value) +fn void LinkedList.link_last(LinkedList* list, Type value) @private { Node *last = list._last; Node *new_node = list.@alloc_node(); @@ -172,7 +172,7 @@ fn void LinkedList.insert(LinkedList* list, usz index, Type element) /** * @require succ != null **/ -private fn void LinkedList.link_before(LinkedList *list, Node *succ, Type value) +fn void LinkedList.link_before(LinkedList *list, Node *succ, Type value) @private { Node* pred = succ.prev; Node* new_node = mem::alloc(Node); @@ -192,7 +192,7 @@ private fn void LinkedList.link_before(LinkedList *list, Node *succ, Type value) /** * @require list && list._first **/ -private fn void LinkedList.unlink_first(LinkedList* list) +fn void LinkedList.unlink_first(LinkedList* list) @private { Node* f = list._first; Node* next = f.next; @@ -267,7 +267,7 @@ fn void! LinkedList.remove_first(LinkedList* list) * @param [&inout] list * @require list._last **/ -private fn void LinkedList.unlink_last(LinkedList *list) @inline +fn void LinkedList.unlink_last(LinkedList *list) @inline @private { Node* l = list._last; Node* prev = l.prev; @@ -287,7 +287,7 @@ private fn void LinkedList.unlink_last(LinkedList *list) @inline /** * @require list != null, x != null **/ -private fn void LinkedList.unlink(LinkedList* list, Node* x) +fn void LinkedList.unlink(LinkedList* list, Node* x) @private { Node* next = x.next; Node* prev = x.prev; diff --git a/lib/std/collections/list.c3 b/lib/std/collections/list.c3 index 4c0571994..96f606e6f 100644 --- a/lib/std/collections/list.c3 +++ b/lib/std/collections/list.c3 @@ -168,7 +168,7 @@ fn Type* List.get_ref(List* list, usz index) @operator(&[]) @inline } -private fn void List.ensure_capacity(List* list) @inline +fn void List.ensure_capacity(List* list) @inline @private { if (list.capacity == list.size) { diff --git a/lib/std/collections/map.c3 b/lib/std/collections/map.c3 index cfe137c95..b21d37d55 100644 --- a/lib/std/collections/map.c3 +++ b/lib/std/collections/map.c3 @@ -5,13 +5,6 @@ const uint DEFAULT_INITIAL_CAPACITY = 16; const uint MAXIMUM_CAPACITY = 1u << 31; const float DEFAULT_LOAD_FACTOR = 0.75; -private struct Entry -{ - uint hash; - Key key; - Value value; - Entry* next; -} struct HashMap { @@ -216,7 +209,7 @@ $endif; // --- private methods -private fn void HashMap.add_entry(HashMap* map, uint hash, Key key, Value value, uint bucket_index) +fn void HashMap.add_entry(HashMap* map, uint hash, Key key, Value value, uint bucket_index) @private { Entry* entry = map.allocator.alloc(Entry.sizeof)!!; *entry = { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] }; @@ -227,7 +220,7 @@ private fn void HashMap.add_entry(HashMap* map, uint hash, Key key, Value value, } } -private fn void HashMap.resize(HashMap* map, uint new_capacity) +fn void HashMap.resize(HashMap* map, uint new_capacity) @private { Entry*[] old_table = map.table; uint old_capacity = old_table.len; @@ -243,18 +236,18 @@ private fn void HashMap.resize(HashMap* map, uint new_capacity) map.threshold = (uint)(new_capacity * map.load_factor); } -private fn uint rehash(uint hash) @inline +fn uint rehash(uint hash) @inline @private { hash ^= (hash >> 20) ^ (hash >> 12); return hash ^ ((hash >> 7) ^ (hash >> 4)); } -private macro uint index_for(uint hash, uint capacity) +macro uint index_for(uint hash, uint capacity) @private { return hash & (capacity - 1); } -private fn void HashMap.transfer(HashMap* map, Entry*[] new_table) +fn void HashMap.transfer(HashMap* map, Entry*[] new_table) @private { Entry*[] src = map.table; uint new_capacity = new_table.len; @@ -273,7 +266,7 @@ private fn void HashMap.transfer(HashMap* map, Entry*[] new_table) } } -private fn void HashMap.put_all_for_create(HashMap* map, HashMap* other_map) +fn void HashMap.put_all_for_create(HashMap* map, HashMap* other_map) @private { if (!other_map.count) return; foreach (Entry *e : other_map.table) @@ -283,7 +276,7 @@ private fn void HashMap.put_all_for_create(HashMap* map, HashMap* other_map) } } -private fn void HashMap.put_for_create(HashMap* map, Key key, Value value) +fn void HashMap.put_for_create(HashMap* map, Key key, Value value) @private { uint hash = rehash(key.hash()); uint i = index_for(hash, map.table.len); @@ -298,12 +291,12 @@ private fn void HashMap.put_for_create(HashMap* map, Key key, Value value) map.create_entry(hash, key, value, i); } -private fn void HashMap.free_internal(HashMap* map, void* ptr) @inline +fn void HashMap.free_internal(HashMap* map, void* ptr) @inline @private { map.allocator.free(ptr)!!; } -private fn bool HashMap.remove_entry_for_key(HashMap* map, Key key) +fn bool HashMap.remove_entry_for_key(HashMap* map, Key key) @private { uint hash = rehash(key.hash()); uint i = index_for(hash, map.table.len); @@ -332,11 +325,19 @@ private fn bool HashMap.remove_entry_for_key(HashMap* map, Key key) return false; } -private fn void HashMap.create_entry(HashMap* map, uint hash, Key key, Value value, int bucket_index) +fn void HashMap.create_entry(HashMap* map, uint hash, Key key, Value value, int bucket_index) @private { Entry *e = map.table[bucket_index]; Entry* entry = map.allocator.alloc(Entry.sizeof)!!; *entry = { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] }; map.table[bucket_index] = entry; map.count++; -} \ No newline at end of file +} + +struct Entry @private +{ + uint hash; + Key key; + Value value; + Entry* next; +} diff --git a/lib/std/core/allocators/arena_allocator.c3 b/lib/std/core/allocators/arena_allocator.c3 index 20489a3dd..c49ec1219 100644 --- a/lib/std/core/allocators/arena_allocator.c3 +++ b/lib/std/core/allocators/arena_allocator.c3 @@ -9,7 +9,7 @@ struct ArenaAllocatorHeader * @require !alignment || math::is_power_of_2(alignment) * @require data `unexpectedly missing the allocator` */ -private fn void*! arena_allocator_function(Allocator* data, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) +fn void*! arena_allocator_function(Allocator* data, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) @private { ArenaAllocator* arena = (ArenaAllocator*)data; bool clear = false; @@ -63,7 +63,7 @@ private fn void*! arena_allocator_function(Allocator* data, usz size, usz alignm * @require mem::aligned_offset(offset, ArenaAllocatorHeader.alignof) == offset * @require this != null **/ -private fn void*! ArenaAllocator._alloc(ArenaAllocator* this, usz size, usz alignment, usz offset) +fn void*! ArenaAllocator._alloc(ArenaAllocator* this, usz size, usz alignment, usz offset) @private { usz total_len = this.data.len; if (size > total_len) return AllocationFailure.CHUNK_TOO_LARGE!; @@ -89,7 +89,7 @@ private fn void*! ArenaAllocator._alloc(ArenaAllocator* this, usz size, usz alig * @require mem::aligned_offset(offset, ArenaAllocatorHeader.alignof) == offset * @require this != null **/ -private fn void*! ArenaAllocator._realloc(ArenaAllocator* this, void *old_pointer, usz size, usz alignment, usz offset) +fn void*! ArenaAllocator._realloc(ArenaAllocator* this, void *old_pointer, usz size, usz alignment, usz offset) @private { assert(old_pointer >= this.data.ptr, "Pointer originates from a different allocator."); usz total_len = this.data.len; diff --git a/lib/std/core/allocators/dynamic_arena.c3 b/lib/std/core/allocators/dynamic_arena.c3 index 4d0f10794..41d73a167 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; -private struct DynamicArenaPage +struct DynamicArenaPage @private { void* memory; void* prev_arena; @@ -9,7 +9,7 @@ private struct DynamicArenaPage void* last_ptr; } -private struct DynamicArenaChunk +struct DynamicArenaChunk @private { usz size; } @@ -18,7 +18,7 @@ private struct DynamicArenaChunk * @require ptr && this * @require this.page `tried to free pointer on invalid allocator` */ -private fn void DynamicArenaAllocator.free(DynamicArenaAllocator* this, void* ptr) +fn void DynamicArenaAllocator.free(DynamicArenaAllocator* this, void* ptr) @private { DynamicArenaPage* current_page = this.page; if (ptr == current_page.last_ptr) @@ -32,7 +32,7 @@ private fn void DynamicArenaAllocator.free(DynamicArenaAllocator* this, void* pt * @require old_pointer && size > 0 * @require this.page `tried to realloc pointer on invalid allocator` */ -private fn void*! DynamicArenaAllocator._realloc(DynamicArenaAllocator* this, void* old_pointer, usz size, usz alignment, usz offset) +fn void*! DynamicArenaAllocator._realloc(DynamicArenaAllocator* this, void* old_pointer, usz size, usz alignment, usz offset) @private { DynamicArenaPage* current_page = this.page; alignment = alignment_for_allocation(alignment); @@ -62,7 +62,7 @@ private fn void*! DynamicArenaAllocator._realloc(DynamicArenaAllocator* this, vo return new_mem; } -private fn void DynamicArenaAllocator.reset(DynamicArenaAllocator* this) +fn void DynamicArenaAllocator.reset(DynamicArenaAllocator* this) @private { DynamicArenaPage* page = this.page; DynamicArenaPage** unused_page_ptr = &this.unused_page; @@ -82,7 +82,7 @@ private fn void DynamicArenaAllocator.reset(DynamicArenaAllocator* this) * @require math::is_power_of_2(alignment) * @require size > 0 */ -private fn void*! DynamicArenaAllocator._alloc_new(DynamicArenaAllocator* this, usz size, usz alignment, usz offset) +fn void*! DynamicArenaAllocator._alloc_new(DynamicArenaAllocator* this, usz size, usz alignment, usz offset) @private { // First, make sure that we can align it, extending the page size if needed. usz page_size = max(this.page_size, mem::aligned_offset(size + DynamicArenaChunk.sizeof + offset, alignment) - offset); @@ -113,7 +113,7 @@ private fn void*! DynamicArenaAllocator._alloc_new(DynamicArenaAllocator* this, * @require size > 0 * @require this */ -private fn void*! DynamicArenaAllocator._alloc(DynamicArenaAllocator* this, usz size, usz alignment, usz offset) +fn void*! DynamicArenaAllocator._alloc(DynamicArenaAllocator* this, usz size, usz alignment, usz offset) @private { alignment = alignment_for_allocation(alignment); DynamicArenaPage* page = this.page; @@ -155,7 +155,7 @@ private fn void*! DynamicArenaAllocator._alloc(DynamicArenaAllocator* this, usz * @require !alignment || math::is_power_of_2(alignment) * @require data `unexpectedly missing the allocator` */ -private fn void*! dynamic_arena_allocator_function(Allocator* data, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) +fn void*! dynamic_arena_allocator_function(Allocator* data, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) @private { DynamicArenaAllocator* allocator = (DynamicArenaAllocator*)data; switch (kind) diff --git a/lib/std/core/allocators/heap_allocator.c3 b/lib/std/core/allocators/heap_allocator.c3 index d55493b8a..9e45caa47 100644 --- a/lib/std/core/allocators/heap_allocator.c3 +++ b/lib/std/core/allocators/heap_allocator.c3 @@ -25,7 +25,7 @@ fn void SimpleHeapAllocator.init(SimpleHeapAllocator* this, MemoryAllocFn alloca * @require !alignment || math::is_power_of_2(alignment) * @require this `unexpectedly missing the allocator` */ -private fn void*! simple_heap_allocator_function(Allocator* this, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) +fn void*! simple_heap_allocator_function(Allocator* this, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) @private { SimpleHeapAllocator* heap = (SimpleHeapAllocator*)this; switch (kind) @@ -74,14 +74,14 @@ fn void*! SimpleHeapAllocator._realloc(SimpleHeapAllocator* this, void* old_poin return new; } -private fn void*! SimpleHeapAllocator._calloc(SimpleHeapAllocator* this, usz bytes) +fn void*! SimpleHeapAllocator._calloc(SimpleHeapAllocator* this, usz bytes) @private { void* data = this._alloc(bytes)?; mem::clear(data, bytes, DEFAULT_MEM_ALIGNMENT); return data; } -private fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) +fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @private { usz aligned_bytes = mem::aligned_offset(bytes, DEFAULT_MEM_ALIGNMENT); if (!this.free_list) @@ -130,7 +130,7 @@ private fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz byte return this.alloc(aligned_bytes); } -private fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_bytes) +fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_bytes) @private { assert(mem::aligned_offset(aligned_bytes, DEFAULT_MEM_ALIGNMENT) == aligned_bytes); char[] result = this.alloc_fn(aligned_bytes + Header.sizeof)?; @@ -141,7 +141,7 @@ private fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz al } -private fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) +fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) @private { // Empty ptr -> do nothing. if (!ptr) return; @@ -208,7 +208,7 @@ private fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) } } -private union Header +union Header @private { struct { diff --git a/lib/std/core/allocators/mem_allocator_fn.c3 b/lib/std/core/allocators/mem_allocator_fn.c3 index 90fde2bb4..be36cfd40 100644 --- a/lib/std/core/allocators/mem_allocator_fn.c3 +++ b/lib/std/core/allocators/mem_allocator_fn.c3 @@ -1,10 +1,10 @@ module std::core::mem::allocator; import libc; -private const Allocator _NULL_ALLOCATOR = { &null_allocator_fn }; -private const Allocator _SYSTEM_ALLOCATOR = { &libc_allocator_fn }; +const Allocator _NULL_ALLOCATOR @private = { &null_allocator_fn }; +const Allocator _SYSTEM_ALLOCATOR @private = { &libc_allocator_fn }; -private fn void*! null_allocator_fn(Allocator* this, usz bytes, usz alignment, usz offset, void* old_pointer, AllocationKind kind) +fn void*! null_allocator_fn(Allocator* this, usz bytes, usz alignment, usz offset, void* old_pointer, AllocationKind kind) @private { switch (kind) { diff --git a/lib/std/core/allocators/temp_allocator.c3 b/lib/std/core/allocators/temp_allocator.c3 index ed42e3084..044046890 100644 --- a/lib/std/core/allocators/temp_allocator.c3 +++ b/lib/std/core/allocators/temp_allocator.c3 @@ -1,7 +1,7 @@ module std::core::mem::allocator; import std::io; -private struct TempAllocatorChunk +struct TempAllocatorChunk @private { usz size; char[*] data; @@ -18,7 +18,7 @@ struct TempAllocator } -private const usz PAGE_IS_ALIGNED = (usz)isz.max + 1u; +const usz PAGE_IS_ALIGNED @private = (usz)isz.max + 1u; struct TempAllocatorPage @@ -52,7 +52,7 @@ fn TempAllocator*! new_temp(usz size, Allocator* backing_allocator) * @require !alignment || math::is_power_of_2(alignment) * @require data `unexpectedly missing the allocator` */ -private fn void*! temp_allocator_function(Allocator* data, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) +fn void*! temp_allocator_function(Allocator* data, usz size, usz alignment, usz offset, void* old_pointer, AllocationKind kind) @private { TempAllocator* arena = (TempAllocator*)data; switch (kind) @@ -86,7 +86,7 @@ private fn void*! temp_allocator_function(Allocator* data, usz size, usz alignme unreachable(); } -private fn void! TempAllocator._free(TempAllocator* this, void* old_pointer) +fn void! TempAllocator._free(TempAllocator* this, void* old_pointer) @private { // TODO fix free assert((uptr)old_pointer >= (uptr)&this.data, "Pointer originates from a different allocator."); @@ -96,7 +96,7 @@ private fn void! TempAllocator._free(TempAllocator* this, void* old_pointer) this.used -= old_size; } } -private fn void! TempAllocator._reset(TempAllocator* this, usz mark) +fn void! TempAllocator._reset(TempAllocator* this, usz mark) @private { TempAllocatorPage *last_page = this.last_page; while (last_page && last_page.mark > mark) @@ -109,14 +109,14 @@ private fn void! TempAllocator._reset(TempAllocator* this, usz mark) this.used = mark; } -private fn void! TempAllocator._free_page(TempAllocator* this, TempAllocatorPage* page) @inline +fn void! TempAllocator._free_page(TempAllocator* this, TempAllocatorPage* page) @inline @private { void* mem = page.start; if (page.is_aligned()) return this.backing_allocator.free_aligned(mem); return this.backing_allocator.free(mem); } -private fn void*! TempAllocator._realloc_page(TempAllocator* this, TempAllocatorPage* page, usz size, usz alignment, usz offset) @inline +fn void*! TempAllocator._realloc_page(TempAllocator* this, TempAllocatorPage* page, usz size, usz alignment, usz offset) @inline @private { // Then the actual start pointer: void* real_pointer = page.start; @@ -144,7 +144,7 @@ private fn void*! TempAllocator._realloc_page(TempAllocator* this, TempAllocator return data; } -private fn void*! TempAllocator._realloc(TempAllocator* this, void* pointer, usz size, usz alignment, usz offset) @inline +fn void*! TempAllocator._realloc(TempAllocator* this, void* pointer, usz size, usz alignment, usz offset) @inline @private { TempAllocatorChunk *chunk = pointer - TempAllocatorChunk.sizeof; if (chunk.size == (usz)-1) @@ -170,7 +170,7 @@ private fn void*! TempAllocator._realloc(TempAllocator* this, void* pointer, usz * @require alignment <= MAX_MEMORY_ALIGNMENT `alignment too big` * @require this != null **/ -private fn void*! TempAllocator._alloc(TempAllocator* this, usz size, usz alignment, usz offset, bool clear) +fn void*! TempAllocator._alloc(TempAllocator* this, usz size, usz alignment, usz offset, bool clear) @private { void* start_mem = &this.data; void* starting_ptr = start_mem + this.used; diff --git a/lib/std/core/conv.c3 b/lib/std/core/conv.c3 index f346dbc16..962a9855e 100644 --- a/lib/std/core/conv.c3 +++ b/lib/std/core/conv.c3 @@ -1,13 +1,13 @@ module std::core::string::conv; -private const uint UTF16_SURROGATE_OFFSET = 0x10000; -private const uint UTF16_SURROGATE_GENERIC_MASK = 0xF800; -private const uint UTF16_SURROGATE_GENERIC_VALUE = 0xD800; -private const uint UTF16_SURROGATE_MASK = 0xFC00; -private const uint UTF16_SURROGATE_CODEPOINT_MASK = 0x03FF; -private const uint UTF16_SURROGATE_BITS = 10; -private const uint UTF16_SURROGATE_LOW_VALUE = 0xDC00; -private const uint UTF16_SURROGATE_HIGH_VALUE = 0xD800; +const uint UTF16_SURROGATE_OFFSET @private = 0x10000; +const uint UTF16_SURROGATE_GENERIC_MASK @private = 0xF800; +const uint UTF16_SURROGATE_GENERIC_VALUE @private = 0xD800; +const uint UTF16_SURROGATE_MASK @private = 0xFC00; +const uint UTF16_SURROGATE_CODEPOINT_MASK @private = 0x03FF; +const uint UTF16_SURROGATE_BITS @private = 10; +const uint UTF16_SURROGATE_LOW_VALUE @private = 0xDC00; +const uint UTF16_SURROGATE_HIGH_VALUE @private = 0xD800; /** * @param c `The utf32 codepoint to convert` diff --git a/lib/std/core/floatparse.c3 b/lib/std/core/floatparse.c3 index 51866de67..9b933630f 100644 --- a/lib/std/core/floatparse.c3 +++ b/lib/std/core/floatparse.c3 @@ -451,7 +451,7 @@ macro double! hexfloat(char[] chars, int $bits, int $emin, int sign) return math::scalbn(y, (int)e2); } -private macro floatparse(String chars, $Type) +macro floatparse(String chars, $Type) @private { int sign = 1; $switch ($Type): diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index e3c9557fb..ac02a4721 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -268,8 +268,8 @@ macro void @pool(;@body) @builtin @body(); } -private tlocal Allocator* thread_allocator = allocator::LIBC_ALLOCATOR; -private tlocal TempAllocator* thread_temp_allocator = null; +tlocal Allocator* thread_allocator @private = allocator::LIBC_ALLOCATOR; +tlocal TempAllocator* thread_temp_allocator @private = null; macro TempAllocator* temp_allocator() { @@ -295,7 +295,8 @@ macro Allocator* current_allocator() } $if (!env::COMPILER_LIBC_AVAILABLE && env::ARCH_TYPE == ArchType.WASM32 || env::ARCH_TYPE == ArchType.WASM64): -private SimpleHeapAllocator wasm_allocator; + +SimpleHeapAllocator wasm_allocator @private; extern int __heap_base; diff --git a/lib/std/core/mem_allocator.c3 b/lib/std/core/mem_allocator.c3 index e28e60bc1..de60e7954 100644 --- a/lib/std/core/mem_allocator.c3 +++ b/lib/std/core/mem_allocator.c3 @@ -98,7 +98,7 @@ fn void Allocator.reset(Allocator* allocator, usz mark = 0) allocator.function(allocator, mark, 0, 0, null, RESET)!!; } -private fn usz alignment_for_allocation(usz alignment) @inline +fn usz alignment_for_allocation(usz alignment) @inline @private { if (alignment < DEFAULT_MEM_ALIGNMENT) { diff --git a/lib/std/core/private/main_stub.c3 b/lib/std/core/private/main_stub.c3 index 6b27a4709..daf8fb29d 100644 --- a/lib/std/core/private/main_stub.c3 +++ b/lib/std/core/private/main_stub.c3 @@ -1,6 +1,6 @@ module std::core::main_stub; -private macro usz _strlen(ptr) +macro usz _strlen(ptr) @private { usz len = 0; while (ptr[len]) len++; @@ -15,7 +15,7 @@ macro int @main_to_void_main(#m, int, char**) return 0; } -private macro String[] args_to_strings(int argc, char** argv) +macro String[] args_to_strings(int argc, char** argv) @private { String *list = malloc(String.sizeof * argc); for (int i = 0; i < argc; i++) @@ -54,14 +54,14 @@ $if (env::OS_TYPE == OsType.WIN32): extern fn Char16** _win_command_line_to_argv_w(ushort* cmd_line, int* argc_ptr) @extern("CommandLineToArgvW"); -private macro String[] win_command_line_to_strings(ushort* cmd_line) +macro String[] win_command_line_to_strings(ushort* cmd_line) @private { int argc; Char16** argv = _win_command_line_to_argv_w(cmd_line, &argc); return wargs_strings(argc, argv); } -private macro String[] wargs_strings(int argc, Char16** argv) +macro String[] wargs_strings(int argc, Char16** argv) @private { String *list = malloc(String.sizeof * argc); for (int i = 0; i < argc; i++) @@ -73,7 +73,7 @@ private macro String[] wargs_strings(int argc, Char16** argv) return list[:argc]; } -private macro void release_wargs(String[] list) +macro void release_wargs(String[] list) @private { foreach (s : list) free(s.ptr); free(list.ptr); diff --git a/lib/std/core/runtime.c3 b/lib/std/core/runtime.c3 index 1215c731f..cb6181289 100644 --- a/lib/std/core/runtime.c3 +++ b/lib/std/core/runtime.c3 @@ -47,7 +47,7 @@ fn TestRunner test_runner_create() import libc; -private TestRunner* current_runner; +TestRunner* current_runner @private; fn void test_panic(String message, String file, String function, uint line) { io::printn("[error]"); diff --git a/lib/std/core/str.c3 b/lib/std/core/str.c3 index df85f7228..0e2673d35 100644 --- a/lib/std/core/str.c3 +++ b/lib/std/core/str.c3 @@ -5,13 +5,13 @@ define String = char[]; define Char32 = uint; define Char16 = ushort; -private const uint SURROGATE_OFFSET = 0x10000; -private const uint SURROGATE_GENERIC_MASK = 0xF800; -private const uint SURROGATE_MASK = 0xFC00; -private const uint SURROGATE_CODEPOINT_MASK = 0x03FF; -private const uint SURROGATE_BITS = 10; -private const uint SURROGATE_LOW_VALUE = 0xDC00; -private const uint SURROGATE_HIGH_VALUE = 0xD800; +const uint SURROGATE_OFFSET @private = 0x10000; +const uint SURROGATE_GENERIC_MASK @private = 0xF800; +const uint SURROGATE_MASK @private = 0xFC00; +const uint SURROGATE_CODEPOINT_MASK @private = 0x03FF; +const uint SURROGATE_BITS @private = 10; +const uint SURROGATE_LOW_VALUE @private = 0xDC00; +const uint SURROGATE_HIGH_VALUE @private = 0xD800; fault NumberConversion { @@ -49,12 +49,12 @@ macro bool char_in_set(char c, String set) return false; } -private macro char_is_space_tab(char c) +macro char_is_space_tab(char c) @private { return c == ' ' || c == '\t'; } -private macro to_integer($Type, String string) +macro to_integer($Type, String string) @private { usz len = string.len; usz index = 0; diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index 67371c2e2..977359251 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -7,13 +7,6 @@ define DynString = VarString; define DString = VarString; define VString = VarString; -private struct StringData -{ - Allocator* allocator; - usz len; - usz capacity; - char[*] chars; -} const usz MIN_CAPACITY = 16; @@ -297,12 +290,12 @@ macro void VarString.append(VarString* str, value) } -private fn StringData* VarString.data(VarString str) @inline +fn StringData* VarString.data(VarString str) @inline @private { return (StringData*)str; } -private fn void VarString.reserve(VarString* str, usz addition) +fn void VarString.reserve(VarString* str, usz addition) @private { StringData* data = str.data(); if (!data) @@ -324,3 +317,11 @@ fn VarString VarString.new_concat(VarString a, VarString b, Allocator* allocator string.append(b); return string; } + +struct StringData @private +{ + Allocator* allocator; + usz len; + usz capacity; + char[*] chars; +} diff --git a/lib/std/hash/adler32.c3 b/lib/std/hash/adler32.c3 index 72b642f78..aaeb414cd 100644 --- a/lib/std/hash/adler32.c3 +++ b/lib/std/hash/adler32.c3 @@ -4,7 +4,7 @@ module std::hash::adler32; -private const uint ADLER_CONST = 65521; +const uint ADLER_CONST @private = 65521; struct Adler32 { diff --git a/lib/std/hash/crc32.c3 b/lib/std/hash/crc32.c3 index e33471fcc..edaba5817 100644 --- a/lib/std/hash/crc32.c3 +++ b/lib/std/hash/crc32.c3 @@ -43,7 +43,7 @@ fn uint encode(char[] data) return ~result; } -private const uint[256] CRC32_TABLE = { +const uint[256] CRC32_TABLE @private = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, diff --git a/lib/std/hash/crc64.c3 b/lib/std/hash/crc64.c3 index f18ffba86..2796e2c12 100644 --- a/lib/std/hash/crc64.c3 +++ b/lib/std/hash/crc64.c3 @@ -43,7 +43,7 @@ fn ulong encode(char[] data) return result; } -private const ulong[256] CRC64_TABLE = { +const ulong[256] CRC64_TABLE @private = { 0x0000000000000000, 0x42f0e1eba9ea3693, 0x85e1c3d753d46d26, 0xc711223cfa3e5bb5, 0x493366450e42ecdf, 0x0bc387aea7a8da4c, 0xccd2a5925d9681f9, 0x8e224479f47cb76a, 0x9266cc8a1c85d9be, 0xd0962d61b56fef2d, 0x17870f5d4f51b498, 0x5577eeb6e6bb820b, diff --git a/lib/std/hash/fnv32a.c3 b/lib/std/hash/fnv32a.c3 index 7582bd176..8b5c4ae2b 100644 --- a/lib/std/hash/fnv32a.c3 +++ b/lib/std/hash/fnv32a.c3 @@ -5,10 +5,10 @@ module std::hash::fnv32a; define Fnv32a = distinct uint; -private const FNV32A_START = 0x811c9dc5; -private const FNV32A_MUL = 0x01000193; +const FNV32A_START @private = 0x811c9dc5; +const FNV32A_MUL @private = 0x01000193; -private macro void @update(uint &h, char x) => h = (h * FNV32A_MUL) ^ x; +macro void @update(uint &h, char x) @private => h = (h * FNV32A_MUL) ^ x; fn void Fnv32a.init(Fnv32a* this) { diff --git a/lib/std/io/dir.c3 b/lib/std/io/dir.c3 index b3a9f1dfa..8c85c7618 100644 --- a/lib/std/io/dir.c3 +++ b/lib/std/io/dir.c3 @@ -4,7 +4,7 @@ import std::io::os; define Path = distinct String; const PREFERRED_SEPARATOR = USE_WIN32_FILESYSTEM ? '\\' : '/'; -private const USE_WIN32_FILESYSTEM = env::OS_TYPE != OsType.WIN32; +const USE_WIN32_FILESYSTEM @private = env::OS_TYPE != OsType.WIN32; fault PathResult { @@ -56,7 +56,7 @@ $else: $endif; } -private fn usz! root_name_len(String path) +fn usz! root_name_len(String path) @private { usz len = path.len; if (!len) return 0; @@ -83,7 +83,7 @@ private fn usz! root_name_len(String path) return 0; } -private fn void! normalize_path(String* path_ref) +fn void! normalize_path(String* path_ref) @private { String path = *path_ref; if (!path.len) return; diff --git a/lib/std/io/io_fileinfo.c3 b/lib/std/io/io_fileinfo.c3 index 187839b83..d648ffddd 100644 --- a/lib/std/io/io_fileinfo.c3 +++ b/lib/std/io/io_fileinfo.c3 @@ -11,12 +11,12 @@ $case MACOSX: $case IOS: $case WATCHOS: $case TVOS: -private struct DarwinTimespec +struct DarwinTimespec @private { long tv_sec; long tv_nsec; } -private struct Darwin64Stat +struct Darwin64Stat @private { int st_dev; ushort st_mode; diff --git a/lib/std/io/io_formatter_private.c3 b/lib/std/io/io_formatter_private.c3 index d1ee62716..d4c0c56ef 100644 --- a/lib/std/io/io_formatter_private.c3 +++ b/lib/std/io/io_formatter_private.c3 @@ -1,19 +1,19 @@ module std::io; -private fn void! Formatter.left_adjust(Formatter* this, usz len) +fn void! Formatter.left_adjust(Formatter* this, usz len) @private { if (!this.flags.left) return; for (usz l = len; l < this.width; l++) this.out(' ')?; } -private fn void! Formatter.right_adjust(Formatter* this, usz len) +fn void! Formatter.right_adjust(Formatter* this, usz len) @private { if (this.flags.left) return; for (usz l = len; l < this.width; l++) this.out(' ')?; } -private fn uint128 int_from_variant(variant arg, bool *is_neg) +fn uint128 int_from_variant(variant arg, bool *is_neg) @private { *is_neg = false; if (arg.type.kindof == TypeKind.POINTER) @@ -60,7 +60,7 @@ private fn uint128 int_from_variant(variant arg, bool *is_neg) } } -private fn FloatType float_from_variant(variant arg) +fn FloatType float_from_variant(variant arg) @private { $if (env::F128_SUPPORT): if (arg.type == float128.typeid) return *((float128*)arg.ptr); @@ -115,7 +115,7 @@ private fn FloatType float_from_variant(variant arg) * @param maxlen "the maximum len that can be read." * @return "The result of the atoi." **/ -private fn uint simple_atoi(char* buf, usz maxlen, usz* len_ptr) @inline +fn uint simple_atoi(char* buf, usz maxlen, usz* len_ptr) @inline @private { uint i = 0; usz len = *len_ptr; @@ -131,7 +131,7 @@ private fn uint simple_atoi(char* buf, usz maxlen, usz* len_ptr) @inline } -private fn void! Formatter.out_substr(Formatter *this, String str) +fn void! Formatter.out_substr(Formatter *this, String str) @private { usz l = conv::utf8_codepoints(str); uint prec = this.prec; @@ -151,7 +151,7 @@ private fn void! Formatter.out_substr(Formatter *this, String str) return this.left_adjust(l); } -private fn void! Formatter.etoa(Formatter* this, FloatType value) +fn void! Formatter.etoa(Formatter* this, FloatType value) @private { // check for NaN and special values if (!value || value != value || value < -FloatType.max || value > FloatType.max) @@ -245,7 +245,7 @@ private fn void! Formatter.etoa(Formatter* this, FloatType value) } // internal ftoa for fixed decimal floating point -private fn void! Formatter.ftoa(Formatter* this, FloatType value) +fn void! Formatter.ftoa(Formatter* this, FloatType value) @private { char[PRINTF_FTOA_BUFFER_SIZE] buf @noinit; usz len = 0; @@ -379,7 +379,7 @@ private fn void! Formatter.ftoa(Formatter* this, FloatType value) return this.out_reverse(buf[:len]); } -private fn void! Formatter.ntoa(Formatter* this, uint128 value, bool negative, uint base) +fn void! Formatter.ntoa(Formatter* this, uint128 value, bool negative, uint base) @private { char[PRINTF_NTOA_BUFFER_SIZE] buf @noinit; usz len = 0; @@ -403,7 +403,7 @@ private fn void! Formatter.ntoa(Formatter* this, uint128 value, bool negative, u return this.ntoa_format(buf[:PRINTF_NTOA_BUFFER_SIZE], len, negative, base); } -private fn void! Formatter.ntoa_format(Formatter* this, String buf, usz len, bool negative, uint base) +fn void! Formatter.ntoa_format(Formatter* this, String buf, usz len, bool negative, uint base) @private { // pad leading zeros if (!this.flags.left) @@ -464,14 +464,14 @@ private fn void! Formatter.ntoa_format(Formatter* this, String buf, usz len, boo } -private fn void! Formatter.ntoa_variant(Formatter* this, variant arg, uint base) +fn void! Formatter.ntoa_variant(Formatter* this, variant arg, uint base) @private { bool is_neg; uint128 val = int_from_variant(arg, &is_neg); return this.ntoa(val, is_neg, base) @inline; } -private fn void! Formatter.out_char(Formatter* this, variant arg) +fn void! Formatter.out_char(Formatter* this, variant arg) @private { uint l = 1; // pre padding @@ -499,7 +499,7 @@ private fn void! Formatter.out_char(Formatter* this, variant arg) } -private fn void! Formatter.out_reverse(Formatter* this, String buf) +fn void! Formatter.out_reverse(Formatter* this, String buf) @private { usz buffer_start_idx = this.idx; usz len = buf.len; @@ -518,19 +518,21 @@ private fn void! Formatter.out_reverse(Formatter* this, String buf) return this.left_adjust(this.idx - buffer_start_idx); } -private fn void! printf_advance_format(usz format_len, usz *index_ptr) @inline +fn void! printf_advance_format(usz format_len, usz *index_ptr) @inline @private { usz val = ++(*index_ptr); if (val >= format_len) return FormattingFault.UNTERMINATED_FORMAT!; } -private fn variant! next_variant(variant* args_ptr, usz args_len, usz* arg_index_ptr) @inline +fn variant! next_variant(variant* args_ptr, usz args_len, usz* arg_index_ptr) @inline @private { if (*arg_index_ptr >= args_len) return FormattingFault.MISSING_ARG!; return args_ptr[(*arg_index_ptr)++]; } -private fn int! printf_parse_format_field(variant* args_ptr, usz args_len, usz* args_index_ptr, char* format_ptr, usz format_len, usz* index_ptr) @inline +fn int! printf_parse_format_field( + variant* args_ptr, usz args_len, usz* args_index_ptr, + char* format_ptr, usz format_len, usz* index_ptr) @inline @private { char c = format_ptr[*index_ptr]; if (c >= '0' && c <= '9') return simple_atoi(format_ptr, format_len, index_ptr); diff --git a/lib/std/io/io_printf.c3 b/lib/std/io/io_printf.c3 index 76ceb144a..673c7608d 100644 --- a/lib/std/io/io_printf.c3 +++ b/lib/std/io/io_printf.c3 @@ -15,16 +15,83 @@ fault PrintFault MISSING_ARG, } +fault FormattingFault +{ + UNTERMINATED_FORMAT, + MISSING_ARG, + INVALID_WIDTH_ARG, + INVALID_FORMAT_TYPE, +} define OutputFn = fn void!(char c, void* buffer); define ToStringFunction = fn String(void* value, Allocator *allocator); define ToFormatFunction = fn void!(void* value, Formatter* formatter); define FloatType = double; -private define StringFunctionMap = HashMap; -private define FormatterFunctionMap = HashMap; -private FormatterFunctionMap toformat_functions; -private StringFunctionMap tostring_functions; +fn usz! printf(String format, args...) @maydiscard +{ + Formatter formatter; + formatter.init(&out_putchar_fn); + return formatter.vprintf(format, args); +} + +define printfln = printfn; + +fn usz! printfn(String format, args...) @maydiscard +{ + Formatter formatter; + formatter.init(&out_putchar_fn); + usz len = formatter.vprintf(format, args)?; + putchar('\n'); + return len + 1; +} + +fn usz! VarString.printf(VarString* str, String format, args...) @maydiscard +{ + Formatter formatter; + formatter.init(&out_string_append_fn, str); + return formatter.vprintf(format, args); +} + +fn usz! VarString.printfn(VarString* str, String format, args...) @maydiscard +{ + Formatter formatter; + formatter.init(&out_string_append_fn, str); + usz len = formatter.vprintf(format, args)?; + str.append('\n'); + return len + 1; +} + +fn char[]! bprintf(char[] buffer, String format, args...) @maydiscard +{ + Formatter formatter; + BufferData data = { .buffer = buffer }; + formatter.init(&out_buffer_fn, &data); + usz size = formatter.vprintf(format, args)?; + return buffer[:size]; +} + +fn usz! File.printf(File file, String format, args...) @maydiscard +{ + Formatter formatter; + formatter.init(&out_fputchar_fn, &file); + return formatter.vprintf(format, args)?; +} + +fn usz! File.printfn(File file, String format, args...) @maydiscard +{ + Formatter formatter; + formatter.init(&out_fputchar_fn, &file); + usz len = formatter.vprintf(format, args)?; + file.putc('\n')?; + file.flush(); + return len + 1; +} + +fn usz! Formatter.printf(Formatter* this, String format, args...) +{ + return this.vprintf(format, args) @inline; +} struct Formatter { @@ -91,7 +158,7 @@ static initialize @priority(101) } } -private fn void! Formatter.out(Formatter* this, char c) +fn void! Formatter.out(Formatter* this, char c) @private { this.out_fn(c, this.data)?; } @@ -131,7 +198,8 @@ macro bool! Formatter.print_with_function(Formatter* this, variant arg) } return false; } -private fn void! Formatter.out_str(Formatter* this, variant arg) + +fn void! Formatter.out_str(Formatter* this, variant arg) @private { switch (arg.type.kindof) { @@ -250,113 +318,43 @@ private fn void! Formatter.out_str(Formatter* this, variant arg) } } -fault FormattingFault -{ - UNTERMINATED_FORMAT, - MISSING_ARG, - INVALID_WIDTH_ARG, - INVALID_FORMAT_TYPE, -} -private fn void! out_buffer_fn(char c, void *data) +fn void! out_buffer_fn(char c, void *data) @private { BufferData *buffer_data = data; if (buffer_data.written >= buffer_data.buffer.len) return PrintFault.BUFFER_EXCEEDED!; buffer_data.buffer[buffer_data.written++] = c; } -private fn void! out_null_fn(char c @unused, void* data @unused) +fn void! out_null_fn(char c @unused, void* data @unused) @private { } -private fn void! out_putchar_fn(char c, void* data @unused) +fn void! out_putchar_fn(char c, void* data @unused) @private { libc::putchar(c); } -private fn void! out_fputchar_fn(char c, void* data) +fn void! out_fputchar_fn(char c, void* data) @private { File* f = data; f.putc(c)?; } -private fn void! out_string_append_fn(char c, void* data) +fn void! out_string_append_fn(char c, void* data) @private { VarString* s = data; s.append_char(c); } -fn usz! printf(String format, args...) @maydiscard -{ - Formatter formatter; - formatter.init(&out_putchar_fn); - return formatter.vprintf(format, args); -} -define printfln = printfn; - -fn usz! printfn(String format, args...) @maydiscard -{ - Formatter formatter; - formatter.init(&out_putchar_fn); - usz len = formatter.vprintf(format, args)?; - putchar('\n'); - return len + 1; -} - -fn usz! VarString.printf(VarString* str, String format, args...) @maydiscard -{ - Formatter formatter; - formatter.init(&out_string_append_fn, str); - return formatter.vprintf(format, args); -} - -fn usz! VarString.printfn(VarString* str, String format, args...) @maydiscard -{ - Formatter formatter; - formatter.init(&out_string_append_fn, str); - usz len = formatter.vprintf(format, args)?; - str.append('\n'); - return len + 1; -} - -private struct BufferData +struct BufferData @private { char[] buffer; usz written; } -fn char[]! bprintf(char[] buffer, String format, args...) @maydiscard -{ - Formatter formatter; - BufferData data = { .buffer = buffer }; - formatter.init(&out_buffer_fn, &data); - usz size = formatter.vprintf(format, args)?; - return buffer[:size]; -} - -fn usz! File.printf(File file, String format, args...) @maydiscard -{ - Formatter formatter; - formatter.init(&out_fputchar_fn, &file); - return formatter.vprintf(format, args)?; -} - -fn usz! File.printfn(File file, String format, args...) @maydiscard -{ - Formatter formatter; - formatter.init(&out_fputchar_fn, &file); - usz len = formatter.vprintf(format, args)?; - file.putc('\n')?; - file.flush(); - return len + 1; -} - -fn usz! Formatter.printf(Formatter* this, String format, args...) -{ - return this.vprintf(format, args) @inline; -} fn usz! Formatter.vprintf(Formatter* this, String format, variant[] variants) { @@ -497,3 +495,7 @@ fn usz! Formatter.vprintf(Formatter* this, String format, variant[] variants) return this.idx; } +define StringFunctionMap = HashMap @private; +define FormatterFunctionMap = HashMap @private; +FormatterFunctionMap toformat_functions @private; +StringFunctionMap tostring_functions @private; diff --git a/lib/std/math/math.c3 b/lib/std/math/math.c3 index 88d708901..c34ce25fb 100644 --- a/lib/std/math/math.c3 +++ b/lib/std/math/math.c3 @@ -395,13 +395,13 @@ macro tanh(x) => (exp(2.0 * x) - 1.0) / (exp(2.0 * x) + 1.0); **/ macro trunc(x) => $$trunc(x); -private macro lerp(x, y, amount) => x + (y - x) * amount; -private macro reflect(x, y) +macro lerp(x, y, amount) @private => x + (y - x) * amount; +macro reflect(x, y) @private { var dot = x.dot(y); return x - 2 * y * dot; } -private macro normalize(x) +macro normalize(x) @private { var len = x.length(); if (len == 0) return x; @@ -662,7 +662,7 @@ macro next_power_of_2(x) return y; } -private macro equals_vec(v1, v2) +macro equals_vec(v1, v2) @private { var $elements = v1.len; var abs_diff = math::abs(v1 - v2); diff --git a/lib/std/math/math.matrix.c3 b/lib/std/math/math.matrix.c3 index 9211cd416..d79de3f52 100644 --- a/lib/std/math/math.matrix.c3 +++ b/lib/std/math/math.matrix.c3 @@ -412,19 +412,19 @@ fn Matrix4x4 perspective(Real fov, Real aspect_ratio, Real near, Real far) } -private macro matrix_component_mul(mat, val) +macro matrix_component_mul(mat, val) @private { var $Type = Real[<$typeof(mat.m).len>]; return $typeof(*mat) { .m = val * ($Type)mat.m }; } -private macro matrix_add(mat, mat2) +macro matrix_add(mat, mat2) @private { var $Type = Real[<$typeof(mat.m).len>]; return $typeof(*mat) { .m = ($Type)mat.m + ($Type)mat2.m }; } -private macro matrix_sub(mat, mat2) +macro matrix_sub(mat, mat2) @private { var $Type = Real[<$typeof(mat.m).len>]; return $typeof(*mat) { .m = ($Type)mat.m - ($Type)mat2.m }; diff --git a/lib/std/math/math.simple_random.c3 b/lib/std/math/math.simple_random.c3 index afc6fb391..7b026571a 100644 --- a/lib/std/math/math.simple_random.c3 +++ b/lib/std/math/math.simple_random.c3 @@ -5,16 +5,16 @@ struct SimpleRandom long seed; } -private const long SIMPLE_RANDOM_MULTIPLIER = 0x5DEECE66D; -private const long SIMPLE_RANDOM_ADDEND = 0xB; -private const long SIMPLE_RANDOM_MASK = (1i64 << 48) - 1; +const long SIMPLE_RANDOM_MULTIPLIER @private = 0x5DEECE66D; +const long SIMPLE_RANDOM_ADDEND @private = 0xB; +const long SIMPLE_RANDOM_MASK @private = (1i64 << 48) - 1; -private fn long simple_random_initial_scramble(long seed) +fn long simple_random_initial_scramble(long seed) @private { return (seed ^ SIMPLE_RANDOM_MULTIPLIER) & SIMPLE_RANDOM_MASK; } -private fn int SimpleRandom.next(SimpleRandom* r, int bits) +fn int SimpleRandom.next(SimpleRandom* r, int bits) @private { long nextseed = (r.seed * SIMPLE_RANDOM_MULTIPLIER + SIMPLE_RANDOM_ADDEND) & SIMPLE_RANDOM_MASK; r.seed = nextseed; diff --git a/lib/std/math/math_easings.c3 b/lib/std/math/math_easings.c3 index a6c67d2fa..5a1aade5b 100644 --- a/lib/std/math/math_easings.c3 +++ b/lib/std/math/math_easings.c3 @@ -196,6 +196,6 @@ fn float elastic_inout(float t, float b, float c, float d) @inline : a * math::pow(2.0f, -10 * t) * math::sin((t * d - s) * (2 * (float)math::PI) / p) * 0.5f + c + b; } -private macro sq(x) => x * x; -private macro cube(x) => x * x * x; +macro sq(x) @private => x * x; +macro cube(x) @private => x * x * x; diff --git a/lib/std/math/math_i128.c3 b/lib/std/math/math_i128.c3 index 81b27a14b..89d7039d7 100644 --- a/lib/std/math/math_i128.c3 +++ b/lib/std/math/math_i128.c3 @@ -70,7 +70,7 @@ fn int128 __modti3(int128 a, int128 b) @extern("__modti3") @weak return __umodti3(unsigned_a, unsigned_b) ^ sign + (-sign); } -private union Int128bits +union Int128bits @private { struct { @@ -139,7 +139,7 @@ fn int128 __ashlti3(int128 a, uint b) @extern("__ashlti3") @weak // Returns: a * b -private fn int128 __mulddi3(ulong a, ulong b) +fn int128 __mulddi3(ulong a, ulong b) @private { Int128bits r; const ulong LOWER_MASK = 0xffff_ffff; @@ -177,7 +177,7 @@ fn int128 __fixdfti(double a) @weak @extern("__fixdfti") => fixint(a); fn int128 __fixsfti(float a) @weak @extern("__fixsfti") => fixint(a); -private macro float_from_i128($Type, a) +macro float_from_i128($Type, a) @private { var $Rep; $switch ($Type): @@ -236,7 +236,7 @@ private macro float_from_i128($Type, a) return bitcast((($Rep)sign & SIGN_BIT) | ((($Rep)e + ($Rep)EXP_BIAS) << SIGNIFICANT_BITS) | (($Rep)a & ($Rep)MANTISSA_MASK), $Type); } -private macro float_from_u128($Type, a) +macro float_from_u128($Type, a) @private { var $Rep; $switch ($Type): @@ -291,7 +291,7 @@ private macro float_from_u128($Type, a) } -private macro fixuint(a) +macro fixuint(a) @private { var $Rep; $switch ($typeof(a)): @@ -335,7 +335,7 @@ private macro fixuint(a) return (uint128)significand << (exponent - SIGNIFICANT_BITS); } -private macro fixint(a) +macro fixint(a) @private { var $Rep; $switch ($typeof(a)): diff --git a/lib/std/math/math_nolibc/__cosdf.c3 b/lib/std/math/math_nolibc/__cosdf.c3 index 55f00a215..6d63bc6a3 100644 --- a/lib/std/math/math_nolibc/__cosdf.c3 +++ b/lib/std/math/math_nolibc/__cosdf.c3 @@ -19,10 +19,10 @@ $if (!env::COMPILER_LIBC_AVAILABLE): */ /* |cos(x) - c(x)| < 2**-34.1 (~[-5.37e-11, 5.295e-11]). */ -private const double C0 = -0x1ffffffd0c5e81.0p-54; /* -0.499999997251031003120 */ -private const double C1 = 0x155553e1053a42.0p-57; /* 0.0416666233237390631894 */ -private const double C2 = -0x16c087e80f1e27.0p-62; /* -0.00138867637746099294692 */ -private const double C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */ +const double C0 @private = -0x1ffffffd0c5e81.0p-54; /* -0.499999997251031003120 */ +const double C1 @private = 0x155553e1053a42.0p-57; /* 0.0416666233237390631894 */ +const double C2 @private = -0x16c087e80f1e27.0p-62; /* -0.00138867637746099294692 */ +const double C3 @private = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */ fn float __cosdf(double x) @extern("__cosdf") @weak { diff --git a/lib/std/math/math_nolibc/atan.c3 b/lib/std/math/math_nolibc/atan.c3 index 0b8b80302..5eee61767 100644 --- a/lib/std/math/math_nolibc/atan.c3 +++ b/lib/std/math/math_nolibc/atan.c3 @@ -2,21 +2,21 @@ module std::math::nolibc::atan; $if (!env::COMPILER_LIBC_AVAILABLE): -private const double[*] ATANHI = { +const double[*] ATANHI @private = { 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ }; -private const double[*] ATANLO = { +const double[*] ATANLO @private = { 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ }; -private const double[*] AT = { +const double[*] AT @private = { 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ @@ -91,21 +91,21 @@ fn double _atan(double x) @weak @extern("atan") return sign ? -z : z; } -private const float[*] ATANHIF = { +const float[*] ATANHIF @private = { 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */ 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */ 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */ 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */ }; -private const float[*] ATANLOF = { +const float[*] ATANLOF @private = { 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */ 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */ 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */ 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */ }; -private const float[*] ATF = { +const float[*] ATF @private = { 3.3333328366e-01, -1.9999158382e-01, 1.4253635705e-01, @@ -177,9 +177,9 @@ fn float _atanf(float x) @weak @extern("atanf") return sign ? -z : z; } -private const PI_LO = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ +const PI_LO @private = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ -private macro void extract_words(double d, uint* hi, uint* lo) +macro void extract_words(double d, uint* hi, uint* lo) @private { ulong rep = bitcast(d, ulong); *hi = (uint)(rep >> 32); @@ -254,8 +254,8 @@ fn double _atan2(double y, double x) @weak @extern("atan2") } } -private const float PI_F = 3.1415927410e+00; /* 0x40490fdb */ -private const float PI_LO_F = -8.7422776573e-08; /* 0xb3bbbd2e */ +const float PI_F @private = 3.1415927410e+00; /* 0x40490fdb */ +const float PI_LO_F @private = -8.7422776573e-08; /* 0xb3bbbd2e */ fn float _atan2f(float y, float x) @weak @extern("atan2f") { diff --git a/lib/std/math/math_nolibc/exp2.c3 b/lib/std/math/math_nolibc/exp2.c3 index 6c6ef20ad..48f53ce04 100644 --- a/lib/std/math/math_nolibc/exp2.c3 +++ b/lib/std/math/math_nolibc/exp2.c3 @@ -2,7 +2,7 @@ module std::math::nolibc; $if (!env::COMPILER_LIBC_AVAILABLE): -private macro uint _top12f(float x) => bitcast(x, uint) >> 20; +macro uint _top12f(float x) @private => bitcast(x, uint) >> 20; fn float _exp2f(float x) @extern("exp2f") @weak @@ -44,7 +44,7 @@ fn float _exp2f(float x) @extern("exp2f") @weak return (float)y; } -private fn double _exp2_specialcase(double tmp, ulong sbits, ulong ki) +fn double _exp2_specialcase(double tmp, ulong sbits, ulong ki) @private { if (ki & 0x80000000 == 0) { @@ -77,7 +77,7 @@ private fn double _exp2_specialcase(double tmp, ulong sbits, ulong ki) } -private macro uint _top12d(double x) +macro uint _top12d(double x) @private { return (uint)(bitcast(x, ulong) >> 52); } diff --git a/lib/std/math/math_nolibc/math_nolibc.c3 b/lib/std/math/math_nolibc/math_nolibc.c3 index 2ed1c084b..1a0190bb8 100644 --- a/lib/std/math/math_nolibc/math_nolibc.c3 +++ b/lib/std/math/math_nolibc/math_nolibc.c3 @@ -3,15 +3,15 @@ module std::math::nolibc; const double TOINT = 1 / math::DOUBLE_EPSILON; const double TOINT15 = 1.5 / math::DOUBLE_EPSILON; const float TOINTF = (float)(1 / math::FLOAT_EPSILON); -private const double S1PI2 = math::PI_2; /* 0x3FF921FB, 0x54442D18 */ -private const double S2PI2 = math::PI; /* 0x400921FB, 0x54442D18 */ -private const double S3PI2 = math::PI + math::PI_2; /* 0x4012D97C, 0x7F3321D2 */ -private const double S4PI2 = math::PI + math::PI; /* 0x401921FB, 0x54442D18 */ +const double S1PI2 @private = math::PI_2; /* 0x3FF921FB, 0x54442D18 */ +const double S2PI2 @private = math::PI; /* 0x400921FB, 0x54442D18 */ +const double S3PI2 @private = math::PI + math::PI_2; /* 0x4012D97C, 0x7F3321D2 */ +const double S4PI2 @private = math::PI + math::PI; /* 0x401921FB, 0x54442D18 */ // Shared between expf, exp2f and powf. -private const EXP2F_TABLE_BITS = 5; -private const EXP2F_POLY_ORDER = 3; -private struct Exp2fData +const EXP2F_TABLE_BITS @private = 5; +const EXP2F_POLY_ORDER @private = 3; +struct Exp2fData @private { ulong[1 << EXP2F_TABLE_BITS] tab; double shift_scaled; @@ -21,7 +21,7 @@ private struct Exp2fData double[EXP2F_POLY_ORDER] poly_scaled; } -private const Exp2fData __EXP2F_DATA = { +const Exp2fData __EXP2F_DATA @private = { .tab = { 0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51, 0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1, @@ -49,7 +49,7 @@ const EXP_TABLE_BITS = 7; const EXP_POLY_ORDER = 5; const EXP2_POLY_ORDER = 5; const EXP_DATA_WIDTH = 1 << EXP_TABLE_BITS; -private struct Exp2Data +struct Exp2Data @private { double invln2N; double shift; diff --git a/lib/std/math/math_vector.c3 b/lib/std/math/math_vector.c3 index 3d77c8015..544f85472 100644 --- a/lib/std/math/math_vector.c3 +++ b/lib/std/math/math_vector.c3 @@ -78,7 +78,7 @@ fn Vec3 Vec3.rotate_axis(Vec3 v, Vec3 axis, double angle) => rotate_axis_angle(v fn Vec3f Vec3f.unproject(Vec3f v, Matrix4f projection, Matrix4f view) => unproject3(v, projection, view); fn Vec3 Vec3.unproject(Vec3 v, Matrix4 projection, Matrix4 view) => unproject3(v, projection, view); -private macro towards(v, target, max_distance) +macro towards(v, target, max_distance) @private { var delta = target - v; var square = delta.length_sq(); @@ -90,7 +90,7 @@ private macro towards(v, target, max_distance) return v + delta * max_distance / dist; } -private macro clamp_magnitude(v, min, max) +macro clamp_magnitude(v, min, max) @private { var length = v.dot(v); if (length > 0) @@ -103,14 +103,14 @@ private macro clamp_magnitude(v, min, max) return v; } -private macro rotate(v, angle) +macro rotate(v, angle) @private { var c = math::cos(angle); var s = math::sin(angle); return $typeof(v) { v[0] * c - v[1] * s, v[0] * s + v[1] * c }; } -private macro perpendicular3(v) +macro perpendicular3(v) @private { var min = math::abs(v[0]); $typeof(v) cardinal_axis = { 1, 0, 0 }; @@ -129,20 +129,20 @@ private macro perpendicular3(v) return cross3(v, cardinal_axis); } -private macro cross3(v1, v2) +macro cross3(v1, v2) @private { var a = v1.yzx * v2.zxy; var b = v1.zxy * v2.yzx; return a - b; } -private macro transform2(v, mat) +macro transform2(v, mat) @private { return $typeof(v) { mat.m00 * v[0] + mat.m10 * v[1] + mat.30, mat.m01 * v[0] + mar.m11 * v[1] + mat.31 }; } -private macro transform3(v, mat) +macro transform3(v, mat) @private { return $typeof(v) { mat.m00 * v[0] + mat.m10 * v[1] + mat.m20 * v[2] + mat.m30, @@ -152,21 +152,21 @@ private macro transform3(v, mat) } -private macro angle3(v1, v2) +macro angle3(v1, v2) @private { var len = v1.cross(v2).length(); var dot = v1.dot(v2); return math::atan2(len, dot); } -private macro void ortho_normalize3(v1, v2) +macro void ortho_normalize3(v1, v2) @private { var v1n = *v1 = v1.normalize(); var vn1 = v1n.cross(*v2).normalize(); *v2 = v1n.cross(vn1); } -private macro rotate_by_quat3(v, q) +macro rotate_by_quat3(v, q) @private { return $typeof(v) { v[0] * (q.i * q.i + q.l * q.l - q.j * q.j - q.k * q.k) @@ -181,7 +181,7 @@ private macro rotate_by_quat3(v, q) }; } -private macro rotate_axis_angle(v, axis, angle) +macro rotate_axis_angle(v, axis, angle) @private { axis = axis.normalize(); @@ -195,7 +195,7 @@ private macro rotate_axis_angle(v, axis, angle) return v + wv + wwv; } -private macro matrix_look_at($Type, eye, target, up) +macro matrix_look_at($Type, eye, target, up) @private { var vz = (eye - target).normalize(); var vx = up.cross(vz).normalize(); @@ -209,7 +209,7 @@ private macro matrix_look_at($Type, eye, target, up) }; } -private macro unproject3(v, m1, m2) +macro unproject3(v, m1, m2) @private { return v; /* @@ -233,7 +233,7 @@ return v; };*/ } -private macro barycenter3(p, a, b, c) +macro barycenter3(p, a, b, c) @private { var v0 = b - a; var v1 = c - a; @@ -249,7 +249,7 @@ private macro barycenter3(p, a, b, c) return $typeof(p) { 1 - y - z, y, z }; } -private macro refract3(v, n, r) +macro refract3(v, n, r) @private { var dot = v.dot(n); var d = 1 - r * r * (1 - dot * dot); diff --git a/lib/std/os/win32/files.c3 b/lib/std/os/win32/files.c3 index b23841b72..e960f76e4 100644 --- a/lib/std/os/win32/files.c3 +++ b/lib/std/os/win32/files.c3 @@ -2,11 +2,11 @@ module std::os::win32::files; $if (env::OS_TYPE == OsType.WIN32): /* -private extern ulong _win32_GetCurrentDirectoryW(ulong, Char16* buffer) @extern("GetCurrentDirectoryW"); -private extern bool _win32_CreateSymbolicLinkW(Char16* symlink_file, Char16* target_file, ulong flags) @extern("CreateSymbolicLinkW"); -private extern bool _win32_CreateDirectoryW(Char16* path_name, void* security_attributes) @extern("CreateDirectoryW"); -private extern bool _win32_DeleteFileW(Char16* file) @extern("DeleteFileW"); -private extern bool _win32_CopyFileW(Char16* from_file, Char16* to_file, bool no_overwrite) @extern("CopyFileW"); -private extern ulong _win32_GetFullPathNameW(Char16* file_name, ulong buffer_len, Char16* buffer, Char16** file_part) @extern("GetFullPathNameW"); +extern ulong _win32_GetCurrentDirectoryW(ulong, Char16* buffer) @extern("GetCurrentDirectoryW"); +extern bool _win32_CreateSymbolicLinkW(Char16* symlink_file, Char16* target_file, ulong flags) @extern("CreateSymbolicLinkW"); +extern bool _win32_CreateDirectoryW(Char16* path_name, void* security_attributes) @extern("CreateDirectoryW"); +extern bool _win32_DeleteFileW(Char16* file) @extern("DeleteFileW"); +extern bool _win32_CopyFileW(Char16* from_file, Char16* to_file, bool no_overwrite) @extern("CopyFileW"); +extern ulong _win32_GetFullPathNameW(Char16* file_name, ulong buffer_len, Char16* buffer, Char16** file_part) @extern("GetFullPathNameW"); */ $endif; \ No newline at end of file diff --git a/lib/std/threads/os/thread_posix.c3 b/lib/std/threads/os/thread_posix.c3 index 12ae42317..ac0f0f541 100644 --- a/lib/std/threads/os/thread_posix.c3 +++ b/lib/std/threads/os/thread_posix.c3 @@ -156,7 +156,7 @@ fn void! NativeConditionVariable.wait_timeout(NativeConditionVariable* cond, Nat } -private fn void* callback(void* arg) +fn void* callback(void* arg) @private { PosixThreadData *data = arg; return (void*)(iptr)data.thread_fn(data.arg); @@ -211,7 +211,7 @@ fn void native_thread_yield() sched_yield(); } -private struct PosixThreadData +struct PosixThreadData @private { ThreadFn thread_fn; void* arg; diff --git a/lib/std/threads/os/thread_win32.c3 b/lib/std/threads/os/thread_win32.c3 index 73c4f9146..33b07c146 100644 --- a/lib/std/threads/os/thread_win32.c3 +++ b/lib/std/threads/os/thread_win32.c3 @@ -215,7 +215,7 @@ fn void! NativeConditionVariable.broadcast(NativeConditionVariable* cond) if (have_waiters && !win32_SetEvent(cond.event_all)) return ThreadFault.SIGNAL_FAILED!; } -private fn void! timedwait(NativeConditionVariable* cond, NativeMutex* mtx, uint timeout) +fn void! timedwait(NativeConditionVariable* cond, NativeMutex* mtx, uint timeout) @private { win32_EnterCriticalSection(&cond.waiters_count_lock); cond.waiters_count++; diff --git a/resources/examples/contextfree/boolerr.c3 b/resources/examples/contextfree/boolerr.c3 index 244ef82a3..8454a2efe 100644 --- a/resources/examples/contextfree/boolerr.c3 +++ b/resources/examples/contextfree/boolerr.c3 @@ -11,7 +11,7 @@ struct Summary bool ok; } -private struct StringData +struct StringData @private { Allocator allocator; usz len; diff --git a/resources/examples/fasta.c3 b/resources/examples/fasta.c3 index 810005dab..667d80f34 100644 --- a/resources/examples/fasta.c3 +++ b/resources/examples/fasta.c3 @@ -15,7 +15,7 @@ fn float fasta_rand(float max_val) return max_val * seed / IM; } -private String alu = +String alu @private = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" diff --git a/resources/examples/hash.c3 b/resources/examples/hash.c3 index b8521b2f1..78087c13a 100644 --- a/resources/examples/hash.c3 +++ b/resources/examples/hash.c3 @@ -91,7 +91,7 @@ fn ulong fnv64a(char[] data) return h; } -private const uint[256] CRC32_TABLE = { +const uint[256] CRC32_TABLE @private = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, @@ -158,7 +158,7 @@ private const uint[256] CRC32_TABLE = { 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; -private const ulong[256] CRC64_TABLE = { +const ulong[256] CRC64_TABLE @private = { 0x0000000000000000, 0x42f0e1eba9ea3693, 0x85e1c3d753d46d26, 0xc711223cfa3e5bb5, 0x493366450e42ecdf, 0x0bc387aea7a8da4c, 0xccd2a5925d9681f9, 0x8e224479f47cb76a, 0x9266cc8a1c85d9be, 0xd0962d61b56fef2d, 0x17870f5d4f51b498, 0x5577eeb6e6bb820b, diff --git a/resources/examples/notworking/acornvm/avm_array.c3 b/resources/examples/notworking/acornvm/avm_array.c3 index a68ed419c..936975bf4 100644 --- a/resources/examples/notworking/acornvm/avm_array.c3 +++ b/resources/examples/notworking/acornvm/avm_array.c3 @@ -49,7 +49,7 @@ fn int Value.isClosure(Value* val) return val.isEnc(ArrEnc) && arr_info(val)->flags1 & TypeClo; } -private fn ArrInfo.fill(ArrInfo* a, AuintIdx start, AuintIdx end, Value value) @inline +fn ArrInfo.fill(ArrInfo* a, AuintIdx start, AuintIdx end, Value value) @inline @private { for (AuintIdx i = start; i < end; i++) a.arr[i] = value; } diff --git a/resources/examples/notworking/acornvm/lexer.c3 b/resources/examples/notworking/acornvm/lexer.c3 index 6ea12e589..85d588224 100644 --- a/resources/examples/notworking/acornvm/lexer.c3 +++ b/resources/examples/notworking/acornvm/lexer.c3 @@ -360,7 +360,7 @@ bool lexScanNumber(LexInfo *lex) { } /** List of all reserved names (excluding literals) */ -private VmLiterals ReservedNames[] = { +VmLiterals ReservedNames[] @private = { SymAnd, SymAsync, SymBaseurl, diff --git a/resources/testproject/foo.c3 b/resources/testproject/foo.c3 index 082f06080..208b6f3c1 100644 --- a/resources/testproject/foo.c3 +++ b/resources/testproject/foo.c3 @@ -9,10 +9,10 @@ struct Foo extern fn void printf(char *hello); -private fn void ofke() +fn void ofke() @private {} -private fn void exple() {} +fn void exple() @private{} fn void test() { diff --git a/src/compiler/ast.c b/src/compiler/ast.c index abca52fb6..cdf066ec3 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -25,13 +25,12 @@ Decl *decl_new_ct(DeclKind kind, SourceSpan span) return decl; } -Decl *decl_new(DeclKind decl_kind, const char *name, SourceSpan span, Visibility visibility) +Decl *decl_new(DeclKind decl_kind, const char *name, SourceSpan span) { Decl *decl = decl_calloc(); decl->decl_kind = decl_kind; decl->span = span; decl->name = name; - decl->visibility = visibility; return decl; } @@ -42,13 +41,12 @@ bool decl_is_ct_var(Decl *decl) UNREACHABLE; } -Decl *decl_new_with_type(const char *name, SourceSpan loc, DeclKind decl_type, Visibility visibility) +Decl *decl_new_with_type(const char *name, SourceSpan loc, DeclKind decl_type) { Decl *decl = decl_calloc(); decl->decl_kind = decl_type; decl->name = name; decl->span = loc; - decl->visibility = visibility; TypeKind kind = TYPE_POISONED; switch (decl_type) { @@ -227,7 +225,7 @@ void decl_set_external_name(Decl *decl) if (!name) name = "$anon"; // "extern" or the module has no prefix? - if (decl->visibility == VISIBLE_EXTERN || decl->unit->module->no_extprefix) + if (decl->is_extern || decl->unit->module->no_extprefix) { assert(decl->name || decl->unit->module->no_extprefix); decl->extname = name; @@ -260,9 +258,9 @@ void decl_set_external_name(Decl *decl) decl->extname = scratch_buffer_copy(); } -Decl *decl_new_var(const char *name, SourceSpan loc, TypeInfo *type, VarDeclKind kind, Visibility visibility) +Decl *decl_new_var(const char *name, SourceSpan loc, TypeInfo *type, VarDeclKind kind) { - Decl *decl = decl_new(DECL_VAR, name, loc, visibility); + Decl *decl = decl_new(DECL_VAR, name, loc); decl->var.kind = kind; decl->var.type_info = type; return decl; @@ -274,7 +272,6 @@ Decl *decl_new_generated_var(Type *type, VarDeclKind kind, SourceSpan span) decl->decl_kind = DECL_VAR; decl->span = span; decl->name = NULL; - decl->visibility = VISIBLE_LOCAL; decl->var.kind = kind; decl->type = type; decl->alignment = type ? type_alloca_alignment(type) : 0; diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 38f27a996..2d04827c9 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -658,9 +658,10 @@ typedef struct Decl_ const char *extname; SourceSpan span; DeclKind decl_kind : 7; - Visibility visibility : 3; ResolveStatus resolve_status : 3; bool is_packed : 1; + bool is_extern : 1; + bool is_private : 1; bool is_substruct : 1; bool has_variable_array : 1; bool is_value : 1; @@ -2100,10 +2101,10 @@ bool context_set_module(ParseContext *context, Path *path, const char **generic_ // --- Decl functions -Decl *decl_new(DeclKind decl_kind, const char *name, SourceSpan span, Visibility visibility); +Decl *decl_new(DeclKind decl_kind, const char *name, SourceSpan span); Decl *decl_new_ct(DeclKind kind, SourceSpan span); -Decl *decl_new_with_type(const char *name, SourceSpan span, DeclKind decl_type, Visibility visibility); -Decl *decl_new_var(const char *name, SourceSpan span, TypeInfo *type, VarDeclKind kind, Visibility visibility); +Decl *decl_new_with_type(const char *name, SourceSpan span, DeclKind decl_type); +Decl *decl_new_var(const char *name, SourceSpan span, TypeInfo *type, VarDeclKind kind); Decl *decl_new_generated_var(Type *type, VarDeclKind kind, SourceSpan span); void decl_set_external_name(Decl *decl); const char *decl_to_name(Decl *decl); @@ -2297,7 +2298,6 @@ const char *macos_sysroot(void); MacSDK *macos_sysroot_sdk_information(const char *sdk_path); WindowsSDK *windows_get_sdk(void); const char *windows_cross_compile_library(void); -INLINE bool visible_external(Visibility visibility); void c_abi_func_create(FunctionPrototype *proto); @@ -3058,10 +3058,6 @@ INLINE void ast_prepend(AstId *first, Ast *ast) *first = astid(ast); } -INLINE bool visible_external(Visibility visibility) -{ - return visibility == VISIBLE_PUBLIC || visibility == VISIBLE_EXTERN; -} INLINE Ast *ast_next(AstId *current_ptr) { diff --git a/src/compiler/context.c b/src/compiler/context.c index 44f3e06f6..4625859c4 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -129,7 +129,7 @@ void unit_register_external_symbol(CompilationUnit *unit, Decl *decl) void decl_register(Decl *decl) { - if (decl->visibility != VISIBLE_PUBLIC && decl->visibility != VISIBLE_EXTERN) return; + if (decl->is_private) return; switch (decl->decl_kind) { case DECL_INITIALIZE: @@ -305,7 +305,6 @@ bool unit_add_import(CompilationUnit *unit, Path *path, bool private_import) Decl *import = decl_calloc(); import->span = path->span; import->decl_kind = DECL_IMPORT; - import->visibility = VISIBLE_LOCAL; import->import.path = path; import->import.private = private_import; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index f4547dce8..dca29000d 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -745,6 +745,7 @@ typedef enum ATTR_MACRO = 1 << 13, ATTR_INITIALIZER = 1 << 14, ATTR_FINALIZER = 1 << 15, + ATTR_DEFINE = 1 << 16, ATTR_XXLIZER = ATTR_INITIALIZER | ATTR_FINALIZER } AttributeDomain; @@ -778,6 +779,7 @@ typedef enum ATTRIBUTE_OVERLAP, ATTRIBUTE_PACKED, ATTRIBUTE_PRIORITY, + ATTRIBUTE_PRIVATE, ATTRIBUTE_PURE, ATTRIBUTE_REFLECT, ATTRIBUTE_SECTION, diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 14ccc81c3..761cbddc5 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -332,7 +332,7 @@ void llvm_set_global_tls(Decl *decl) { if (!decl->var.is_threadlocal) return; LLVMThreadLocalMode thread_local_mode = LLVMGeneralDynamicTLSModel; - if (!decl->var.is_addr && (decl->visibility == VISIBLE_LOCAL || decl->visibility == VISIBLE_MODULE) && !decl->is_external_visible) + if (!decl->var.is_addr && decl->is_private && !decl->is_external_visible) { thread_local_mode = LLVMLocalDynamicTLSModel; } @@ -412,7 +412,7 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) else { LLVMUnnamedAddr addr = LLVMGlobalUnnamedAddr; - if (decl->is_external_visible || visible_external(decl->visibility)) addr = LLVMLocalUnnamedAddr; + if (!decl->is_private || decl->is_external_visible) addr = LLVMLocalUnnamedAddr; LLVMSetUnnamedAddress(decl->backend_ref, addr); } if (decl->section) @@ -431,7 +431,7 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) { UNREACHABLE } - if (decl->visibility != VISIBLE_EXTERN) + if (!decl->is_extern) { LLVMSetInitializer(decl->backend_ref, init_value); if (optional_ref) @@ -442,27 +442,28 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) LLVMSetGlobalConstant(global_ref, decl->var.kind == VARDECL_CONST); - Visibility visibility = decl->visibility; - if (decl->is_external_visible) visibility = VISIBLE_PUBLIC; - switch (visibility) + if (decl->is_extern) { - case VISIBLE_MODULE: + LLVMSetLinkage(global_ref, LLVMExternalLinkage); + if (optional_ref) LLVMSetLinkage(optional_ref, LLVMExternalLinkage); + } + else if (decl->is_private && !decl->is_external_visible) + { + if (decl->var.kind == VARDECL_CONST || decl->var.kind == VARDECL_GLOBAL) + { LLVMSetVisibility(global_ref, LLVMProtectedVisibility); if (optional_ref) LLVMSetVisibility(optional_ref, LLVMProtectedVisibility); - break; - case VISIBLE_PUBLIC: - LLVMSetVisibility(global_ref, LLVMDefaultVisibility); - if (optional_ref) LLVMSetVisibility(optional_ref, LLVMDefaultVisibility); - break; - case VISIBLE_EXTERN: - LLVMSetLinkage(global_ref, LLVMExternalLinkage); - if (optional_ref) LLVMSetLinkage(optional_ref, LLVMExternalLinkage); - //LLVMSetVisibility(decl->backend_ref, LLVMDefaultVisibility); - break; - case VISIBLE_LOCAL: + } + else + { LLVMSetLinkage(global_ref, LLVMInternalLinkage); if (optional_ref) LLVMSetLinkage(optional_ref, LLVMInternalLinkage); - break; + } + } + else + { + LLVMSetVisibility(global_ref, LLVMDefaultVisibility); + if (optional_ref) LLVMSetVisibility(optional_ref, LLVMDefaultVisibility); } decl->backend_ref = global_ref; @@ -758,19 +759,14 @@ void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value) llvm_set_linkonce(c, value); return; } - Visibility visibility = decl->visibility; - if (decl->is_external_visible) visibility = VISIBLE_PUBLIC; - switch (visibility) + if (decl->is_private && !decl->is_external_visible) { - case VISIBLE_MODULE: - case VISIBLE_PUBLIC: - llvm_set_linkonce(c, value); - break; - case VISIBLE_EXTERN: - case VISIBLE_LOCAL: - LLVMSetVisibility(value, LLVMHiddenVisibility); - LLVMSetLinkage(value, LLVMLinkerPrivateLinkage); - break; + LLVMSetVisibility(value, LLVMHiddenVisibility); + LLVMSetLinkage(value, LLVMLinkerPrivateLinkage); + } + else + { + llvm_set_linkonce(c, value); } } @@ -920,10 +916,18 @@ void llvm_add_global_decl(GenContext *c, Decl *decl) { assert(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST); - const char *name = decl->unit->module == c->code_module ? "tempglobal" : decl_get_extname(decl); + bool same_module = decl->unit->module == c->code_module; + const char *name = same_module ? "tempglobal" : decl_get_extname(decl); decl->backend_ref = llvm_add_global(c, name, decl->type, decl->alignment); llvm_set_alignment(decl->backend_ref, decl->alignment); - + if (!same_module) + { + LLVMSetLinkage(decl->backend_ref, LLVMExternalLinkage); + } + if (decl->var.kind == VARDECL_CONST) + { + LLVMSetGlobalConstant(decl->backend_ref, true); + } if (IS_OPTIONAL(decl)) { scratch_buffer_clear(); @@ -1028,7 +1032,7 @@ void llvm_append_function_attributes(GenContext *c, Decl *decl) llvm_attribute_add_string(c, function, "wasm-export-name", decl_get_extname(decl), -1); } } - if (decl->visibility == VISIBLE_EXTERN && arch_is_wasm(platform_target.arch)) + if (decl->is_extern && arch_is_wasm(platform_target.arch)) { llvm_attribute_add_string(c, function, "wasm-import-name", decl_get_extname(decl), -1); } @@ -1063,7 +1067,7 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl) case DECL_FUNC: backend_ref = decl->backend_ref = LLVMAddFunction(c->module, decl_get_extname(decl), llvm_get_type(c, decl->type)); llvm_append_function_attributes(c, decl); - if (decl->unit->module == c->code_module && !decl->is_external_visible && !visible_external(decl->visibility)) + if (decl->unit->module == c->code_module && !decl->is_external_visible && decl->is_private) { llvm_set_internal_linkage(backend_ref); } diff --git a/src/compiler/llvm_codegen_debug_info.c b/src/compiler/llvm_codegen_debug_info.c index 8841ea62b..62cdb850f 100644 --- a/src/compiler/llvm_codegen_debug_info.c +++ b/src/compiler/llvm_codegen_debug_info.c @@ -98,7 +98,7 @@ void llvm_emit_debug_global_var(GenContext *c, Decl *global) c->debug.file, loc.row ? loc.row : 1, llvm_get_debug_type(c, global->type), - global->visibility == VISIBLE_LOCAL, + global->is_private, LLVMDIBuilderCreateExpression(c->debug.builder, NULL, 0), NULL, global->alignment); @@ -108,20 +108,13 @@ void llvm_emit_debug_function(GenContext *c, Decl *decl) { LLVMDIFlags flags = LLVMDIFlagZero; if (!decl->func_decl.body) return; - switch (decl->visibility) + if (decl->is_private) { - case VISIBLE_LOCAL: - flags |= LLVMDIFlagPrivate; - break; - case VISIBLE_MODULE: - flags |= LLVMDIFlagProtected; - break; - case VISIBLE_PUBLIC: - case VISIBLE_EXTERN: - flags |= LLVMDIFlagPublic; - break; - default: - UNREACHABLE + flags |= LLVMDIFlagPrivate; + } + else + { + flags |= LLVMDIFlagPublic; } flags |= LLVMDIFlagPrototyped; if (decl->func_decl.signature.attrs.noreturn) flags |= LLVMDIFlagNoReturn; @@ -135,7 +128,7 @@ void llvm_emit_debug_function(GenContext *c, Decl *decl) c->debug.file, row, llvm_get_debug_type(c, decl->type), - decl->visibility == VISIBLE_LOCAL, + decl->is_private, true, row, flags, diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 865c5c2f0..88606df46 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -620,36 +620,27 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl) llvm_emit_debug_function(c, decl); } - Visibility visibility = decl->visibility; - if (decl->is_external_visible) visibility = VISIBLE_PUBLIC; - switch (visibility) + if (decl->is_extern) { - case VISIBLE_EXTERN: - if (decl->is_weak) - { - LLVMSetLinkage(function, LLVMExternalWeakLinkage); - llvm_set_comdat(c, function); - } - else - { - LLVMSetLinkage(function, LLVMExternalLinkage); - } - LLVMSetVisibility(function, LLVMDefaultVisibility); - /* - if (decl->type->function.prototype->call_abi == CALL_X86_STD && platform_target.os == OS_TYPE_WIN32) - { - LLVMSetDLLStorageClass(function, LLVMDLLImportStorageClass); - }*/ - break; - case VISIBLE_PUBLIC: - case VISIBLE_MODULE: - if (decl->is_weak) llvm_set_weak(c, function); - break; - case VISIBLE_LOCAL: - LLVMSetLinkage(function, decl->is_weak ? LLVMLinkerPrivateWeakLinkage : LLVMInternalLinkage); - LLVMSetVisibility(function, LLVMDefaultVisibility); - break;; + if (decl->is_weak) + { + LLVMSetLinkage(function, LLVMExternalWeakLinkage); + llvm_set_comdat(c, function); + } + else + { + LLVMSetLinkage(function, LLVMExternalLinkage); + } + LLVMSetVisibility(function, LLVMDefaultVisibility); + return; } + if (decl->is_private && !decl->is_external_visible) + { + LLVMSetLinkage(function, decl->is_weak ? LLVMLinkerPrivateWeakLinkage : LLVMInternalLinkage); + LLVMSetVisibility(function, LLVMDefaultVisibility); + return; + } + if (decl->is_weak) llvm_set_weak(c, function); } diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index 3c040a991..ce153d978 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -342,7 +342,7 @@ static Expr *parse_lambda(ParseContext *c, Expr *left) advance_and_verify(c, TOKEN_FN); Decl *func = decl_calloc(); func->decl_kind = DECL_FUNC; - func->visibility = VISIBLE_LOCAL; + func->is_private = true; func->func_decl.generated_lambda = NULL; TypeInfo *return_type = NULL; if (!tok_is(c, TOKEN_LPAREN)) @@ -354,14 +354,14 @@ static Expr *parse_lambda(ParseContext *c, Expr *left) Decl **decls = NULL; Variadic variadic = VARIADIC_NONE; int vararg_index = -1; - if (!parse_parameters(c, VISIBLE_LOCAL, &decls, NULL, &variadic, &vararg_index, PARAM_PARSE_LAMBDA)) return false; + if (!parse_parameters(c, &decls, NULL, &variadic, &vararg_index, PARAM_PARSE_LAMBDA)) return false; CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr); Signature *sig = &func->func_decl.signature; sig->vararg_index = vararg_index < 0 ? vec_size(decls) : vararg_index; sig->params = decls; sig->rtype = return_type ? type_infoid(return_type) : 0; sig->variadic = variadic; - if (!parse_attributes(c, &func->attributes)) return poisoned_expr; + if (!parse_attributes(c, &func->attributes, NULL)) return poisoned_expr; if (tok_is(c, TOKEN_IMPLIES)) { @@ -780,7 +780,7 @@ static Expr *parse_call_expr(ParseContext *c, Expr *left) SEMA_ERROR_LAST("Expected an ending ')'. Did you forget a ')' before this ';'?"); return poisoned_expr; } - if (!parse_parameters(c, VISIBLE_LOCAL, &body_args, NULL, NULL, NULL, PARAM_PARSE_CALL)) return poisoned_expr; + if (!parse_parameters(c, &body_args, NULL, NULL, NULL, PARAM_PARSE_CALL)) return poisoned_expr; } if (!tok_is(c, TOKEN_RPAREN)) { diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index cd4761266..e98cc9683 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -2,13 +2,13 @@ #include "parser_internal.h" -static Decl *parse_const_declaration(ParseContext *c, Visibility visibility); -static inline Decl *parse_func_definition(ParseContext *c, Visibility visibility, AstId docs, bool is_interface); +static Decl *parse_const_declaration(ParseContext *c); +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); -#define DECL_VAR_NEW(type__, var__, visible__) decl_new_var(symstr(c), c->span, type__, var__, visible__); +#define DECL_VAR_NEW(type__, var__) decl_new_var(symstr(c), c->span, type__, var__); static bool context_next_is_path_prefix_start(ParseContext *c) @@ -788,7 +788,7 @@ Decl *parse_decl_after_type(ParseContext *c, TypeInfo *type) if (tok_is(c, TOKEN_CT_IDENT)) { - Decl *decl = DECL_VAR_NEW(type, VARDECL_LOCAL_CT, VISIBLE_LOCAL); + Decl *decl = DECL_VAR_NEW(type, VARDECL_LOCAL_CT); advance(c); if (try_consume(c, TOKEN_EQ)) { @@ -799,10 +799,10 @@ Decl *parse_decl_after_type(ParseContext *c, TypeInfo *type) EXPECT_IDENT_FOR_OR("variable name", poisoned_decl); - Decl *decl = DECL_VAR_NEW(type, VARDECL_LOCAL, VISIBLE_LOCAL); + Decl *decl = DECL_VAR_NEW(type, VARDECL_LOCAL); advance(c); - if (!parse_attributes(c, &decl->attributes)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; if (tok_is(c, TOKEN_EQ)) { if (!decl) @@ -821,11 +821,13 @@ Decl *parse_decl_after_type(ParseContext *c, TypeInfo *type) * * @return Decl* (poisoned on error) */ -Decl *parse_decl(ParseContext *c) +Decl *parse_local_decl(ParseContext *c) { if (tok_is(c, TOKEN_CONST)) { - return parse_const_declaration(c, VISIBLE_LOCAL); + ASSIGN_DECL_OR_RET(Decl *decl, parse_const_declaration(c), poisoned_decl); + decl->is_private = true; + return decl; } bool is_threadlocal = try_consume(c, TOKEN_TLOCAL); @@ -841,6 +843,7 @@ Decl *parse_decl(ParseContext *c) } decl->var.is_static = is_static || is_threadlocal; decl->var.is_threadlocal = is_threadlocal; + decl->is_private = true; return decl; } @@ -864,7 +867,7 @@ Expr *parse_decl_or_expr(ParseContext *c, Decl **decl_ref) * : 'const' type? IDENT '=' const_expr * ; */ -static Decl *parse_const_declaration(ParseContext *c, Visibility visibility) +static Decl *parse_const_declaration(ParseContext *c) { advance_and_verify(c, TOKEN_CONST); @@ -874,10 +877,12 @@ static Decl *parse_const_declaration(ParseContext *c, Visibility visibility) { ASSIGN_TYPE_OR_RET(type_info, parse_type(c), poisoned_decl); } - Decl *decl = decl_new_var(symstr(c), c->span, type_info, VARDECL_CONST, visibility); + Decl *decl = decl_new_var(symstr(c), c->span, type_info, VARDECL_CONST); if (!consume_const_name(c, "const")) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; + CONSUME_OR_RET(TOKEN_EQ, poisoned_decl); if (!parse_decl_initializer(c, decl, false)) return poisoned_decl; @@ -897,7 +902,7 @@ Decl *parse_var_decl(ParseContext *c) SEMA_ERROR_HERE("Constants must be declared using 'const' not 'var'."); return poisoned_decl; case TOKEN_IDENT: - decl = DECL_VAR_NEW(NULL, VARDECL_LOCAL, VISIBLE_LOCAL); + decl = DECL_VAR_NEW(NULL, VARDECL_LOCAL); advance(c); if (!tok_is(c, TOKEN_EQ)) { @@ -908,7 +913,7 @@ Decl *parse_var_decl(ParseContext *c) ASSIGN_EXPR_OR_RET(decl->var.init_expr, parse_expr(c), poisoned_decl); break; case TOKEN_CT_IDENT: - decl = DECL_VAR_NEW(NULL, VARDECL_LOCAL_CT, VISIBLE_LOCAL); + decl = DECL_VAR_NEW(NULL, VARDECL_LOCAL_CT); advance(c); if (try_consume(c, TOKEN_EQ)) { @@ -916,7 +921,7 @@ Decl *parse_var_decl(ParseContext *c) } break; case TOKEN_CT_TYPE_IDENT: - decl = DECL_VAR_NEW(NULL, VARDECL_LOCAL_CT_TYPE, VISIBLE_LOCAL); + decl = DECL_VAR_NEW(NULL, VARDECL_LOCAL_CT_TYPE); advance(c); if (try_consume(c, TOKEN_EQ)) { @@ -1025,7 +1030,7 @@ 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) +bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Decl *owner) { while (1) { @@ -1033,6 +1038,15 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref) if (!parse_attribute(c, &attr)) return false; if (!attr) return true; const char *name = attr->name; + if (name == attribute_list[ATTRIBUTE_PRIVATE]) + { + if (!owner) + { + SEMA_ERROR(attr, "'%s' cannot be used here."); + return false; + } + owner->is_private = true; + } FOREACH_BEGIN(Attr *other_attr, *attributes_ref) if (other_attr->name == name) { @@ -1056,7 +1070,7 @@ bool parse_attributes(ParseContext *c, Attr ***attributes_ref) * @param visibility * @return true if parsing succeeded */ -static inline Decl *parse_global_declaration(ParseContext *c, Visibility visibility) +static inline Decl *parse_global_declaration(ParseContext *c) { bool threadlocal = try_consume(c, TOKEN_TLOCAL); @@ -1073,7 +1087,7 @@ static inline Decl *parse_global_declaration(ParseContext *c, Visibility visibil Decl **decls = NULL; while (true) { - decl = DECL_VAR_NEW(type, VARDECL_GLOBAL, visibility); + decl = DECL_VAR_NEW(type, VARDECL_GLOBAL); decl->var.is_threadlocal = threadlocal; if (!try_consume(c, TOKEN_IDENT)) { @@ -1091,7 +1105,7 @@ static inline Decl *parse_global_declaration(ParseContext *c, Visibility visibil // Add the last, or we miss it. if (decls) vec_add(decls, decl); - if (!parse_attributes(c, &decl->attributes)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; if (try_consume(c, TOKEN_EQ)) { if (decls) @@ -1126,7 +1140,7 @@ static inline Decl *parse_global_declaration(ParseContext *c, Visibility visibil * param_declaration ::= type_expression '...'?) (IDENT ('=' initializer)?)? * ; */ -static inline bool parse_param_decl(ParseContext *c, Visibility parent_visibility, Decl*** parameters, bool require_name) +static inline bool parse_param_decl(ParseContext *c, Decl*** parameters, bool require_name) { ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_optional_type(c), false); if (type->optional) @@ -1135,7 +1149,7 @@ static inline bool parse_param_decl(ParseContext *c, Visibility parent_visibilit return false; } bool vararg = try_consume(c, TOKEN_ELLIPSIS); - Decl *param = DECL_VAR_NEW(type, VARDECL_PARAM, parent_visibility); + Decl *param = DECL_VAR_NEW(type, VARDECL_PARAM); param->var.vararg = vararg; if (!try_consume(c, TOKEN_IDENT)) { @@ -1200,7 +1214,7 @@ INLINE bool is_end_of_param_list(ParseContext *c) * parameter ::= type ELLIPSIS? (non_type_ident ('=' expr))? * | ELLIPSIS (CT_TYPE_IDENT | non_type_ident ('=' expr)?)? */ -bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref, Decl **body_params, +bool parse_parameters(ParseContext *c, Decl ***params_ref, Decl **body_params, Variadic *variadic, int *vararg_index_ref, ParameterParseKind parse_kind) { Decl** params = NULL; @@ -1386,7 +1400,7 @@ bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref SEMA_ERROR(type, "Parameters may not be optional."); return false; } - Decl *param = decl_new_var(name, span, type, param_kind, visibility); + Decl *param = decl_new_var(name, span, type, param_kind); param->var.type_info = type; if (!no_name) { @@ -1395,7 +1409,7 @@ bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref if (!parse_decl_initializer(c, param, false)) return poisoned_decl; } } - if (!parse_attributes(c, ¶m->attributes)) return false; + if (!parse_attributes(c, ¶m->attributes, NULL)) return false; if (ellipsis) { var_arg_found = true; @@ -1414,13 +1428,13 @@ bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref * * parameter_type_list ::= '(' parameters ')' */ -static inline bool parse_fn_parameter_list(ParseContext *c, Visibility parent_visibility, Signature *signature, bool is_interface) +static inline bool parse_fn_parameter_list(ParseContext *c, Signature *signature, bool is_interface) { Decl **decls = NULL; CONSUME_OR_RET(TOKEN_LPAREN, false); Variadic variadic = VARIADIC_NONE; int vararg_index = -1; - if (!parse_parameters(c, parent_visibility, &decls, NULL, &variadic, &vararg_index, PARAM_PARSE_FUNC)) return false; + if (!parse_parameters(c, &decls, NULL, &variadic, &vararg_index, PARAM_PARSE_FUNC)) return false; CONSUME_OR_RET(TOKEN_RPAREN, false); signature->vararg_index = vararg_index < 0 ? vec_size(decls) : vararg_index; signature->params = decls; @@ -1467,13 +1481,13 @@ bool parse_struct_body(ParseContext *c, Decl *parent) Decl *member; if (peek(c) != TOKEN_IDENT) { - member = decl_new_with_type(NULL, c->span, decl_kind, parent->visibility); + member = decl_new_with_type(NULL, c->span, decl_kind); advance(c); } else { advance(c); - member = decl_new_with_type(symstr(c), c->span, decl_kind, parent->visibility); + member = decl_new_with_type(symstr(c), c->span, decl_kind); advance_and_verify(c, TOKEN_IDENT); } if (decl_kind == DECL_BITSTRUCT) @@ -1484,7 +1498,7 @@ bool parse_struct_body(ParseContext *c, Decl *parent) } else { - if (!parse_attributes(c, &member->attributes)) return false; + if (!parse_attributes(c, &member->attributes, NULL)) return false; if (!parse_struct_body(c, member)) return decl_poison(parent); } vec_add(parent->strukt.members, member); @@ -1522,7 +1536,7 @@ bool parse_struct_body(ParseContext *c, Decl *parent) SEMA_ERROR_HERE("A valid member name was expected here."); return false; } - Decl *member = DECL_VAR_NEW(type, VARDECL_MEMBER, parent->visibility); + Decl *member = DECL_VAR_NEW(type, VARDECL_MEMBER); vec_add(parent->strukt.members, member); index++; if (index > MAX_MEMBERS) @@ -1531,7 +1545,7 @@ bool parse_struct_body(ParseContext *c, Decl *parent) return false; } advance(c); - if (!parse_attributes(c, &member->attributes)) return false; + if (!parse_attributes(c, &member->attributes, NULL)) return false; if (!try_consume(c, TOKEN_COMMA)) break; if (was_inline) { @@ -1554,18 +1568,18 @@ bool parse_struct_body(ParseContext *c, Decl *parent) * * @param visibility */ -static inline Decl *parse_struct_declaration(ParseContext *c, Visibility visibility) +static inline Decl *parse_struct_declaration(ParseContext *c) { TokenType type = c->tok; advance(c); const char* type_name = type == TOKEN_STRUCT ? "struct" : "union"; - Decl *decl = decl_new_with_type(symstr(c), c->span, decl_from_token(type), visibility); + Decl *decl = decl_new_with_type(symstr(c), c->span, decl_from_token(type)); if (!consume_type_name(c, type_name)) return poisoned_decl; - if (!parse_attributes(c, &decl->attributes)) + if (!parse_attributes(c, &decl->attributes, decl)) { return poisoned_decl; } @@ -1591,7 +1605,7 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) while (!try_consume(c, TOKEN_RBRACE)) { ASSIGN_TYPE_OR_RET(TypeInfo *type, parse_type(c), false); - Decl *member_decl = DECL_VAR_NEW(type, VARDECL_BITMEMBER, VISIBLE_LOCAL); + Decl *member_decl = DECL_VAR_NEW(type, VARDECL_BITMEMBER); if (!try_consume(c, TOKEN_IDENT)) { @@ -1622,18 +1636,19 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) /** * bitstruct_declaration = 'bitstruct' IDENT ':' type bitstruct_body */ -static inline Decl *parse_bitstruct_declaration(ParseContext *c, Visibility visibility) +static inline Decl *parse_bitstruct_declaration(ParseContext *c) { advance_and_verify(c, TOKEN_BITSTRUCT); - Decl *decl = decl_new_with_type(symstr(c), c->span, DECL_BITSTRUCT, visibility); + Decl *decl = decl_new_with_type(symstr(c), c->span, DECL_BITSTRUCT); + if (!consume_type_name(c, "bitstruct")) return poisoned_decl; TRY_CONSUME_OR_RET(TOKEN_COLON, "':' followed by bitstruct type (e.g. 'int') was expected here.", poisoned_decl); ASSIGN_TYPE_OR_RET(decl->bitstruct.base_type, parse_type(c), poisoned_decl); - if (!parse_attributes(c, &decl->attributes)) + if (!parse_attributes(c, &decl->attributes, decl)) { return poisoned_decl; } @@ -1647,9 +1662,9 @@ static inline Decl *parse_bitstruct_declaration(ParseContext *c, Visibility visi } -static inline Decl *parse_top_level_const_declaration(ParseContext *c, Visibility visibility) +static inline Decl *parse_top_level_const_declaration(ParseContext *c) { - ASSIGN_DECL_OR_RET(Decl * decl, parse_const_declaration(c, visibility), poisoned_decl); + ASSIGN_DECL_OR_RET(Decl * decl, parse_const_declaration(c), poisoned_decl); CONSUME_EOS_OR_RET(poisoned_decl); return decl; } @@ -1660,7 +1675,7 @@ static inline Decl *parse_top_level_const_declaration(ParseContext *c, Visibilit * * trailing_block_parameter ::= '@' IDENT ( '(' parameters ')' )? */ -static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl *macro) +static bool parse_macro_arguments(ParseContext *c, Decl *macro) { CONSUME_OR_RET(TOKEN_LPAREN, false); @@ -1668,7 +1683,7 @@ static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl * Variadic variadic = VARIADIC_NONE; int vararg_index = -1; Decl **params = NULL; - if (!parse_parameters(c, visibility, ¶ms, NULL, &variadic, &vararg_index, PARAM_PARSE_MACRO)) return false; + if (!parse_parameters(c, ¶ms, NULL, &variadic, &vararg_index, PARAM_PARSE_MACRO)) return false; macro->func_decl.signature.params = params; macro->func_decl.signature.vararg_index = vararg_index < 0 ? vec_size(params) : vararg_index; macro->func_decl.signature.variadic = variadic; @@ -1677,11 +1692,11 @@ static bool parse_macro_arguments(ParseContext *c, Visibility visibility, Decl * if (try_consume(c, TOKEN_EOS)) { // Consume AT_IDENT - Decl *body_param = decl_new(DECL_BODYPARAM, symstr(c), c->span, visibility); + Decl *body_param = decl_new(DECL_BODYPARAM, symstr(c), c->span); TRY_CONSUME_OR_RET(TOKEN_AT_IDENT, "Expected an ending ')' or a block parameter on the format '@block(...).", false); if (try_consume(c, TOKEN_LPAREN)) { - if (!parse_parameters(c, visibility, &body_param->body_params, NULL, NULL, NULL, PARAM_PARSE_BODY)) return false; + if (!parse_parameters(c, &body_param->body_params, NULL, NULL, NULL, PARAM_PARSE_BODY)) return false; CONSUME_OR_RET(TOKEN_RPAREN, false); } macro->func_decl.body_param = declid(body_param); @@ -1715,19 +1730,26 @@ static inline Expr **parse_generic_parameters(ParseContext *c) return params; } +static inline void decl_add_type(Decl *decl, TypeKind kind) +{ + Type *type = type_new(kind, decl->name); + type->canonical = type; + type->decl = decl; + decl->type = type; +} /** * define_type_body ::= TYPE_IDENT '=' 'distinct'? (func_typedef | type generic_params?) ';' * * func_typedef ::= 'fn' optional_type parameter_type_list */ -static inline Decl *parse_define_type(ParseContext *c, Visibility visibility) +static inline Decl *parse_define_type(ParseContext *c) { advance_and_verify(c, TOKEN_DEFINE); - const char *alias_name = symstr(c); - SourceSpan name_loc = c->span; - DEBUG_LOG("Parse define %s", alias_name); + Decl *decl = decl_new(DECL_POISONED, symstr(c), c->span); + DEBUG_LOG("Parse define %s", decl->name); advance_and_verify(c, TOKEN_TYPE_IDENT); + if (!parse_attributes(c, &decl->attributes, decl)) return false; CONSUME_OR_RET(TOKEN_EQ, poisoned_decl); bool distinct = false; if (tok_is(c, TOKEN_IDENT) && symstr(c) == kw_distinct) @@ -1739,12 +1761,13 @@ static inline Decl *parse_define_type(ParseContext *c, Visibility visibility) // 1. Did we have `fn`? In that case it's a function pointer. if (try_consume(c, TOKEN_FN)) { - Decl *decl = decl_new_with_type(alias_name, name_loc, DECL_TYPEDEF, visibility); + decl->decl_kind = DECL_TYPEDEF; + decl_add_type(decl, TYPE_TYPEDEF); decl->typedef_decl.is_func = true; decl->typedef_decl.is_distinct = distinct; ASSIGN_TYPE_OR_RET(TypeInfo *type_info, parse_optional_type(c), poisoned_decl); decl->typedef_decl.function_signature.rtype = type_infoid(type_info); - if (!parse_fn_parameter_list(c, decl->visibility, &(decl->typedef_decl.function_signature), true)) + if (!parse_fn_parameter_list(c, &(decl->typedef_decl.function_signature), true)) { return poisoned_decl; } @@ -1761,25 +1784,33 @@ static inline Decl *parse_define_type(ParseContext *c, Visibility visibility) { Expr **params = parse_generic_parameters(c); if (!params) return poisoned_decl; - Decl *decl = decl_new(DECL_DEFINE, alias_name, name_loc, visibility); + decl->decl_kind = DECL_DEFINE; + decl_add_type(decl, TYPE_TYPEDEF); decl->define_decl.define_kind = DEFINE_TYPE_GENERIC; 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; } - - Decl *decl = decl_new_with_type(alias_name, name_loc, distinct ? DECL_DISTINCT : DECL_TYPEDEF, visibility); + REMINDER("Distinct fn??"); decl->typedef_decl.type_info = type_info; decl->typedef_decl.is_func = false; if (distinct) { + decl->decl_kind = DECL_DISTINCT; + decl_add_type(decl, TYPE_DISTINCT); TypedefDecl typedef_decl = decl->typedef_decl; // Ensure value semantics. decl->distinct_decl.typedef_decl = typedef_decl; decl->type->type_kind = TYPE_DISTINCT; decl->decl_kind = DECL_DISTINCT; } + else + { + decl->decl_kind = DECL_TYPEDEF; + decl_add_type(decl, TYPE_TYPEDEF); + } RANGE_EXTEND_PREV(decl); CONSUME_EOS_OR_RET(poisoned_decl); return decl; @@ -1790,7 +1821,7 @@ static inline Decl *parse_define_type(ParseContext *c, Visibility visibility) * * identifier_alias ::= path? (IDENT | CONST_IDENT) */ -static inline Decl *parse_define_ident(ParseContext *c, Visibility visibility) +static inline Decl *parse_define_ident(ParseContext *c) { // 1. Store the beginning of the "define". advance_and_verify(c, TOKEN_DEFINE); @@ -1813,7 +1844,7 @@ static inline Decl *parse_define_ident(ParseContext *c, Visibility visibility) } // 3. Set up the "define". - Decl *decl = decl_new(DECL_DEFINE, symstr(c), c->span, visibility); + Decl *decl = decl_new(DECL_DEFINE, symstr(c), c->span); decl->define_decl.define_kind = DEFINE_IDENT_ALIAS; if (decl->name == kw_main) @@ -1884,32 +1915,28 @@ static inline Decl *parse_define_ident(ParseContext *c, Visibility visibility) /** * define_attribute ::= 'define' '@' IDENT '(' parameter_list ')' ('=' attribute_list)? */ -static inline Decl *parse_define_attribute(ParseContext *c, Visibility visibility) +static inline Decl *parse_define_attribute(ParseContext *c) { // 1. Store the beginning of the "define". advance_and_verify(c, TOKEN_DEFINE); - Decl *decl = decl_new(DECL_ATTRIBUTE, symstr(c), c->span, visibility); + Decl *decl = decl_new(DECL_ATTRIBUTE, symstr(c), c->span); advance_and_verify(c, TOKEN_AT_TYPE_IDENT); if (try_consume(c, TOKEN_LPAREN)) { - if (!parse_parameters(c, visibility, &decl->attr_decl.params, NULL, NULL, NULL, PARAM_PARSE_ATTR)) return poisoned_decl; + if (!parse_parameters(c, &decl->attr_decl.params, NULL, NULL, NULL, PARAM_PARSE_ATTR)) return poisoned_decl; CONSUME_OR_RET(TOKEN_RPAREN, poisoned_decl); } Attr **attributes = NULL; - if (try_consume(c, TOKEN_EQ)) - { - while (1) - { - if (!parse_attributes(c, &attributes)) return poisoned_decl; - if (tok_is(c, TOKEN_EOS)) break; - CONSUME_OR_RET(TOKEN_COMMA, poisoned_decl); - } - } + if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; + CONSUME_OR_RET(TOKEN_EQ, poisoned_decl); + CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl); + if (!parse_attributes(c, &attributes, NULL)) return poisoned_decl; + CONSUME_OR_RET(TOKEN_RBRACE, poisoned_decl); decl->attr_decl.attrs = attributes; CONSUME_EOS_OR_RET(poisoned_decl); return decl; @@ -1918,17 +1945,17 @@ static inline Decl *parse_define_attribute(ParseContext *c, Visibility visibilit /** * define_decl ::= DEFINE define_type_body | */ -static inline Decl *parse_define(ParseContext *c, Visibility visibility) +static inline Decl *parse_define(ParseContext *c) { switch (peek(c)) { case TOKEN_AT_TYPE_IDENT: // define @Foo = @inline, @noreturn - return parse_define_attribute(c, visibility); + return parse_define_attribute(c); case TOKEN_TYPE_IDENT: - return parse_define_type(c, visibility); + return parse_define_type(c); default: - return parse_define_ident(c, visibility); + return parse_define_ident(c); } } @@ -2010,20 +2037,19 @@ static inline bool parse_func_macro_header(ParseContext *c, Decl *decl) /** * macro ::= macro_header '(' macro_params ')' compound_statement */ -static inline Decl *parse_macro_declaration(ParseContext *c, Visibility visibility, AstId docs) +static inline Decl *parse_macro_declaration(ParseContext *c, AstId docs) { DeclKind kind = try_consume(c, TOKEN_MACRO) ? DECL_MACRO : DECL_GENERIC; if (kind == DECL_GENERIC) advance_and_verify(c, TOKEN_GENERIC); Decl *decl = decl_calloc(); decl->decl_kind = kind; - decl->visibility = visibility; decl->func_decl.docs = docs; if (!parse_func_macro_header(c, decl)) return poisoned_decl; const char *block_parameter = NULL; - if (!parse_macro_arguments(c, visibility, decl)) return poisoned_decl; + if (!parse_macro_arguments(c, decl)) return poisoned_decl; - if (!parse_attributes(c, &decl->attributes)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; if (tok_is(c, TOKEN_IMPLIES)) { ASSIGN_ASTID_OR_RET(decl->func_decl.body, @@ -2041,13 +2067,13 @@ static inline Decl *parse_macro_declaration(ParseContext *c, Visibility visibili * | FAULT TYPE_IDENT '{' error_data '}' * ; */ -static inline Decl *parse_fault_declaration(ParseContext *c, Visibility visibility) +static inline Decl *parse_fault_declaration(ParseContext *c, bool is_private) { advance(c); // advance_and_verify(context, TOKEN_ERRTYPE); - Decl *decl = decl_new_with_type(symstr(c), c->span, DECL_FAULT, visibility); - + Decl *decl = decl_new_with_type(symstr(c), c->span, DECL_FAULT); + decl->is_private = is_private; if (!consume_type_name(c, "fault")) return poisoned_decl; TypeInfo *type = NULL; @@ -2058,7 +2084,8 @@ static inline Decl *parse_fault_declaration(ParseContext *c, Visibility visibili uint64_t ordinal = 0; while (!try_consume(c, TOKEN_RBRACE)) { - Decl *fault_const = decl_new(DECL_FAULTVALUE, symstr(c), c->span, decl->visibility); + Decl *fault_const = decl_new(DECL_FAULTVALUE, symstr(c), c->span); + fault_const->is_private = is_private; if (!consume_const_name(c, "fault value")) { return poisoned_decl; @@ -2094,7 +2121,7 @@ static inline Decl *parse_fault_declaration(ParseContext *c, Visibility visibili * | type '(' opt_parameter_type_list ')' * ; */ -static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl*** parameters_ref, Visibility parent_visibility) +static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl*** parameters_ref) { ASSIGN_TYPE_OR_RET(*type_ref, parse_type(c), false); @@ -2102,7 +2129,7 @@ static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl*** if (!try_consume(c, TOKEN_LPAREN)) return true; while (!try_consume(c, TOKEN_RPAREN)) { - if (!parse_param_decl(c, parent_visibility, parameters_ref, true)) return false; + if (!parse_param_decl(c, parameters_ref, true)) return false; Decl *last_parameter = VECLAST(*parameters_ref); assert(last_parameter); if (last_parameter->var.vararg) @@ -2139,28 +2166,29 @@ static inline bool parse_enum_spec(ParseContext *c, TypeInfo **type_ref, Decl*** * ; * */ -static inline Decl *parse_enum_declaration(ParseContext *c, Visibility visibility) +static inline Decl *parse_enum_declaration(ParseContext *c, bool is_private) { advance_and_verify(c, TOKEN_ENUM); - Decl *decl = decl_new_with_type(symstr(c), c->span, DECL_ENUM, visibility); - + Decl *decl = decl_new_with_type(symstr(c), c->span, DECL_ENUM); + decl->is_private = is_private; if (!consume_type_name(c, "enum")) return poisoned_decl; TypeInfo *type = NULL; if (try_consume(c, TOKEN_COLON)) { - if (!parse_enum_spec(c, &type, &decl->enums.parameters, visibility)) return poisoned_decl; + if (!parse_enum_spec(c, &type, &decl->enums.parameters)) return poisoned_decl; } - if (!parse_attributes(c, &decl->attributes)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, decl)) return poisoned_decl; CONSUME_OR_RET(TOKEN_LBRACE, poisoned_decl); decl->enums.type_info = type ? type : type_info_new_base(type_int, decl->span); while (!try_consume(c, TOKEN_RBRACE)) { - Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, symstr(c), c->span, decl->visibility); + Decl *enum_const = decl_new(DECL_ENUM_CONSTANT, symstr(c), c->span); + enum_const->is_private = is_private; const char *name = enum_const->name; if (!consume_const_name(c, "enum constant")) { @@ -2219,12 +2247,11 @@ static inline Decl *parse_enum_declaration(ParseContext *c, Visibility visibilit * @param visibility * @return Decl* */ -static inline Decl *parse_func_definition(ParseContext *c, Visibility visibility, AstId docs, bool is_interface) +static inline Decl *parse_func_definition(ParseContext *c, AstId docs, bool is_interface) { advance_and_verify(c, TOKEN_FN); Decl *func = decl_calloc(); func->decl_kind = DECL_FUNC; - func->visibility = visibility; func->func_decl.docs = docs; if (!parse_func_macro_header(c, func)) return poisoned_decl; if (func->name[0] == '@') @@ -2232,8 +2259,8 @@ static inline Decl *parse_func_definition(ParseContext *c, Visibility visibility SEMA_ERROR(func, "Function names may not use '@'."); return false; } - if (!parse_fn_parameter_list(c, visibility, &(func->func_decl.signature), is_interface)) return poisoned_decl; - if (!parse_attributes(c, &func->attributes)) return poisoned_decl; + 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; // TODO remove is_interface = tok_is(c, TOKEN_EOS); @@ -2294,25 +2321,20 @@ static inline Decl *parse_static_top_level(ParseContext *c) } advance(c); Attr *attr = NULL; - if (!parse_attributes(c, &init->attributes)) return poisoned_decl; + if (!parse_attributes(c, &init->attributes, NULL)) return poisoned_decl; ASSIGN_ASTID_OR_RET(init->xxlizer.init, parse_compound_stmt(c), poisoned_decl); RANGE_EXTEND_PREV(init); return init; } -static inline bool check_no_visibility_before(ParseContext *c, Visibility visibility) +static inline bool check_no_visibility_before(ParseContext *c, bool is_private) { - switch (visibility) + if (is_private) { - case VISIBLE_MODULE: - SEMA_ERROR_HERE("Unexpected 'static' before '%s'", symstr(c)); - return false; - case VISIBLE_EXTERN: - SEMA_ERROR_HERE("Unexpected 'extern' before '%s'.", symstr(c)); - return false; - default: - return true; + SEMA_ERROR_HERE("Unexpected 'private' before '%s'", symstr(c)); + return false; } + return true; } @@ -2588,7 +2610,7 @@ static bool parse_docs(ParseContext *c, AstId *docs_ref) static Decl *parse_include(ParseContext *c) { SourceSpan loc = c->span; - Decl *decl = decl_new(DECL_CT_INCLUDE, NULL, loc, VISIBLE_LOCAL); + Decl *decl = decl_new(DECL_CT_INCLUDE, NULL, loc); advance_and_verify(c, TOKEN_CT_INCLUDE); CONSUME_OR_RET(TOKEN_LPAREN, poisoned_decl); const char *str = symstr(c); @@ -2670,20 +2692,6 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) { AstId docs = 0; if (!parse_docs(c, &docs)) return poisoned_decl; - Visibility visibility = VISIBLE_PUBLIC; - switch (c->tok) - { - case TOKEN_PRIVATE: - visibility = VISIBLE_MODULE; - advance(c); - break; - case TOKEN_EXTERN: - visibility = VISIBLE_EXTERN; - advance(c); - default: - break; - } - Decl *decl; TokenType tok = c->tok; if (tok != TOKEN_MODULE && !c->unit->module) @@ -2691,13 +2699,56 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) if (!context_set_module_from_filename(c)) return poisoned_decl; // Pass the docs to the next thing. } - + bool is_private = false; +AFTER_VISIBILITY: switch (tok) { - case TOKEN_MODULE: - if (visibility != VISIBLE_PUBLIC) + case TOKEN_PRIVATE: + if (is_private) { - SEMA_ERROR_HERE("Did not expect visibility before 'module'."); + SEMA_ERROR_HERE("Two 'private' modifiers cannot be used in a row."); + return poisoned_decl; + } + is_private = true; + advance(c); + tok = c->tok; + goto AFTER_VISIBILITY; + case TOKEN_EXTERN: + if (is_private) + { + SEMA_ERROR_HERE("'private' cannot be combined with 'extern'."); + } + advance(c); + tok = c->tok; + switch (tok) + { + case TOKEN_FN: + { + ASSIGN_DECL_OR_RET(decl, parse_func_definition(c, docs, false), poisoned_decl); + break; + } + case TOKEN_CONST: + { + ASSIGN_DECL_OR_RET(decl, parse_top_level_const_declaration(c), poisoned_decl); + break; + } + case TOKEN_IDENT: + case TOKEN_TLOCAL: + case TYPELIKE_TOKENS: + { + ASSIGN_DECL_OR_RET(decl, parse_global_declaration(c), poisoned_decl); + break; + } + default: + SEMA_ERROR_HERE("Expected 'extern' to be followed by a function, constant or global variable."); + return poisoned_decl; + } + decl->is_extern = true; + break; + case TOKEN_MODULE: + if (is_private) + { + SEMA_ERROR_HERE("Did not expect 'private' before 'module'."); return poisoned_decl; } if (!c_ref) @@ -2716,26 +2767,28 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) if (!parse_module(c, docs)) return poisoned_decl; return NULL; case TOKEN_DOCS_START: - if (visibility != VISIBLE_PUBLIC) + if (is_private) { - SEMA_ERROR_HERE("Did not expect doc comments after visibility."); + SEMA_ERROR_HERE("Did not expect doc comments after 'private'."); return poisoned_decl; } SEMA_ERROR_HERE("There are more than one doc comment in a row, that is not allowed."); return poisoned_decl; case TOKEN_DEFINE: { - ASSIGN_DECL_OR_RET(decl, parse_define(c, visibility), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_define(c), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_FN: { - ASSIGN_DECL_OR_RET(decl, parse_func_definition(c, visibility, docs, false), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_func_definition(c, docs, false), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_STATIC: { - if (!check_no_visibility_before(c, visibility)) return poisoned_decl; + if (!check_no_visibility_before(c, is_private)) return poisoned_decl; ASSIGN_DECL_OR_RET(decl, parse_static_top_level(c), poisoned_decl); if (docs) { @@ -2745,7 +2798,7 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) break; } case TOKEN_CT_ASSERT: - if (!check_no_visibility_before(c, visibility)) return poisoned_decl; + if (!check_no_visibility_before(c, is_private)) return poisoned_decl; { ASSIGN_AST_OR_RET(Ast *ast, parse_ct_assert_stmt(c), poisoned_decl); decl = decl_new_ct(DECL_CT_ASSERT, ast->span); @@ -2758,7 +2811,7 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) return decl; } case TOKEN_CT_ECHO: - if (!check_no_visibility_before(c, visibility)) return poisoned_decl; + if (!check_no_visibility_before(c, is_private)) return poisoned_decl; { ASSIGN_AST_OR_RET(Ast *ast, parse_ct_echo_stmt(c), poisoned_decl); decl = decl_new_ct(DECL_CT_ECHO, ast->span); @@ -2772,7 +2825,7 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) } case TOKEN_CT_IF: { - if (!check_no_visibility_before(c, visibility)) return poisoned_decl; + if (!check_no_visibility_before(c, is_private)) return poisoned_decl; ASSIGN_DECL_OR_RET(decl, parse_ct_if_top_level(c), poisoned_decl); if (docs) { @@ -2782,7 +2835,7 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) break; } case TOKEN_IMPORT: - if (!check_no_visibility_before(c, visibility)) return poisoned_decl; + if (!check_no_visibility_before(c, is_private)) return poisoned_decl; if (!c_ref) { SEMA_ERROR_HERE("'import' may not appear inside a compile time statement."); @@ -2797,7 +2850,7 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) return NULL; case TOKEN_CT_SWITCH: { - if (!check_no_visibility_before(c, visibility)) return poisoned_decl; + if (!check_no_visibility_before(c, is_private)) return poisoned_decl; ASSIGN_DECL_OR_RET(decl, parse_ct_switch_top_level(c), poisoned_decl); if (docs) { @@ -2807,7 +2860,7 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) break; } case TOKEN_CT_INCLUDE: - if (!check_no_visibility_before(c, visibility)) return poisoned_decl; + if (!check_no_visibility_before(c, is_private)) return poisoned_decl; if (docs) { SEMA_ERROR(astptr(docs), "Unexpected doc comment before $include, did you mean to use a regular comment?"); @@ -2817,38 +2870,48 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) break; case TOKEN_BITSTRUCT: { - ASSIGN_DECL_OR_RET(decl, parse_bitstruct_declaration(c, visibility), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_bitstruct_declaration(c), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_CONST: { - ASSIGN_DECL_OR_RET(decl, parse_top_level_const_declaration(c, visibility), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_top_level_const_declaration(c), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_STRUCT: case TOKEN_UNION: { - ASSIGN_DECL_OR_RET(decl, parse_struct_declaration(c, visibility), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_struct_declaration(c), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_GENERIC: case TOKEN_MACRO: { - ASSIGN_DECL_OR_RET(decl, parse_macro_declaration(c, visibility, docs), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_macro_declaration(c, docs), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_ENUM: { - ASSIGN_DECL_OR_RET(decl, parse_enum_declaration(c, visibility), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_enum_declaration(c, is_private), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_FAULT: { - ASSIGN_DECL_OR_RET(decl, parse_fault_declaration(c, visibility), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_fault_declaration(c, is_private), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_IDENT: - return parse_global_declaration(c, visibility); + { + ASSIGN_DECL_OR_RET(decl, parse_global_declaration(c), poisoned_decl); + if (is_private) decl->is_private = is_private; + break; + } case TOKEN_EOF: SEMA_ERROR_LAST("Expected a top level declaration"); return poisoned_decl; @@ -2867,7 +2930,8 @@ Decl *parse_top_level_statement(ParseContext *c, ParseContext **c_ref) case TOKEN_TLOCAL: case TYPELIKE_TOKENS: { - ASSIGN_DECL_OR_RET(decl, parse_global_declaration(c, visibility), poisoned_decl); + ASSIGN_DECL_OR_RET(decl, parse_global_declaration(c), poisoned_decl); + if (is_private) decl->is_private = is_private; break; } case TOKEN_EOS: diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index c325e0033..e2204afc6 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -85,7 +85,7 @@ static inline Ast *parse_declaration_stmt(ParseContext *c) { // Consts don't have multiple declarations. Ast *decl_stmt = new_ast(AST_DECLARE_STMT, c->span); - ASSIGN_DECL_OR_RET(decl_stmt->declare_stmt, parse_decl(c), poisoned_ast); + ASSIGN_DECL_OR_RET(decl_stmt->declare_stmt, parse_local_decl(c), poisoned_ast); RANGE_EXTEND_PREV(decl_stmt); CONSUME_EOS_OR_RET(poisoned_ast); return decl_stmt; @@ -100,12 +100,14 @@ static inline Ast *parse_declaration_stmt(ParseContext *c) if (result->ast_kind == AST_DECLARE_STMT) { result->declare_stmt->var.is_threadlocal = is_threadlocal; - result->declare_stmt->var.is_static = is_static; + result->declare_stmt->var.is_static = is_static || is_threadlocal; + result->declare_stmt->is_private = true; return result; } FOREACH_BEGIN(Decl *var, result->decls_stmt) var->var.is_threadlocal = is_threadlocal; - var->var.is_static = is_static; + var->var.is_static = is_static || is_threadlocal; + var->is_private = true; FOREACH_END(); return result; } @@ -113,7 +115,7 @@ static inline Ast *parse_declaration_stmt(ParseContext *c) static inline Decl *parse_optional_label(ParseContext *c, Ast *parent) { if (!tok_is(c, TOKEN_CONST_IDENT)) return NULL; - Decl *decl = decl_new(DECL_LABEL, symstr(c), c->span, VISIBLE_LOCAL); + Decl *decl = decl_new(DECL_LABEL, symstr(c), c->span); decl->label.parent = astid(parent); advance_and_verify(c, TOKEN_CONST_IDENT); if (!try_consume(c, TOKEN_COLON)) @@ -720,7 +722,7 @@ static inline bool parse_foreach_var(ParseContext *c, Ast *foreach) { foreach->foreach_stmt.value_by_ref = true; } - Decl *var = decl_new_var(symstr(c), c->span, type, VARDECL_LOCAL, VISIBLE_LOCAL); + Decl *var = decl_new_var(symstr(c), c->span, type, VARDECL_LOCAL); if (!try_consume(c, TOKEN_IDENT)) { if (type) diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index ddc21fe50..ca0b0607c 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -38,7 +38,7 @@ TypeInfo *parse_type(ParseContext *c); TypeInfo *parse_optional_type(ParseContext *c); TypeInfo *parse_type_with_base(ParseContext *c, TypeInfo *type_info); Expr* parse_constant_expr(ParseContext *c); -Decl *parse_decl(ParseContext *c); +Decl *parse_local_decl(ParseContext *c); Expr *parse_integer(ParseContext *c, Expr *left); Expr *parse_decl_or_expr(ParseContext *c, Decl **decl_ref); void recover_top_level(ParseContext *c); @@ -48,7 +48,7 @@ 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); +bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Decl *owner); bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type); Expr *parse_ct_expression_list(ParseContext *c, bool allow_decl); @@ -56,7 +56,7 @@ Expr *parse_expression_list(ParseContext *c, bool allow_decls); Decl *parse_decl_after_type(ParseContext *c, TypeInfo *type); Decl *parse_var_decl(ParseContext *c); -bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref, Decl **body_params, +bool parse_parameters(ParseContext *c, Decl ***params_ref, Decl **body_params, Variadic *variadic, int *vararg_index_ref, ParameterParseKind parse_kind); bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat, bool vasplat); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index cd076df56..a70301ab4 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1976,6 +1976,12 @@ static bool bitstruct_cast(Expr *expr, Type *from_type, Type *to, Type *to_type) bool cast(Expr *expr, Type *to_type) { + if (to_type == type_void) + { + expr->type = type_void; + return true; + } + assert(!type_is_optional(to_type)); Type *from_type = expr->type; bool from_is_optional = false; diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index c130533ce..718159507 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -854,6 +854,8 @@ Type *sema_analyse_function_signature(SemaContext *context, Decl *parent, CallAB static inline bool sema_analyse_typedef(SemaContext *context, Decl *decl) { + if (!sema_analyse_attributes(context, decl, decl->attributes, ATTR_DEFINE)) return decl_poison(decl); + if (decl->typedef_decl.is_func) { Type *func_type = sema_analyse_function_signature(context, decl, CALL_C, &decl->typedef_decl.function_signature, false); @@ -1282,7 +1284,7 @@ static inline bool unit_add_base_extension_method(CompilationUnit *unit, Type *p if (!method_like->has_extname) { scratch_buffer_clear(); - if (method_like->visibility <= VISIBLE_MODULE) + if (method_like->is_private) { scratch_buffer_append(parent_type->name); scratch_buffer_append_char('$'); @@ -1297,7 +1299,7 @@ static inline bool unit_add_base_extension_method(CompilationUnit *unit, Type *p method_like->extname = scratch_buffer_copy(); } DEBUG_LOG("Method-like '%s.%s' analysed.", parent_type->name, method_like->name); - if (method_like->visibility == VISIBLE_LOCAL) + if (method_like->is_private) { vec_add(unit->module->private_method_extensions, method_like); } @@ -1338,7 +1340,7 @@ static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type if (!method_like->has_extname) { scratch_buffer_clear(); - if (method_like->visibility <= VISIBLE_MODULE) + if (method_like->is_private) { scratch_buffer_append(parent->extname); scratch_buffer_append_char('$'); @@ -1353,7 +1355,7 @@ static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type method_like->extname = scratch_buffer_copy(); } DEBUG_LOG("Method-like '%s.%s' analysed.", parent->name, method_like->name); - if (parent->unit->module == unit->module || method_like->visibility != VISIBLE_LOCAL) + if (parent->unit->module == unit->module || !method_like->is_private) { vec_add(parent->methods, method_like); } @@ -1418,12 +1420,16 @@ static const char *attribute_domain_to_string(AttributeDomain domain) return "static initializer"; case ATTR_FINALIZER: return "static finalizer"; + case ATTR_DEFINE: + return "define"; case ATTR_XXLIZER: UNREACHABLE } UNREACHABLE } +#define EXPORTED_USER_DEFINED_TYPES ATTR_ENUM | ATTR_UNION | ATTR_STRUCT +#define USER_DEFINED_TYPES EXPORTED_USER_DEFINED_TYPES | ATTR_BITSTRUCT static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, AttributeDomain domain) { AttributeType type = attr->attr_kind; @@ -1433,9 +1439,9 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, [ATTRIBUTE_BIGENDIAN] = ATTR_BITSTRUCT, [ATTRIBUTE_BUILTIN] = ATTR_MACRO | ATTR_FUNC, [ATTRIBUTE_CDECL] = ATTR_FUNC, - [ATTRIBUTE_EXPORT] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | ATTR_ENUM | ATTR_UNION | ATTR_STRUCT, - [ATTRIBUTE_EXTNAME] = (AttributeDomain)~(ATTR_CALL | ATTR_BITSTRUCT | ATTR_MACRO | ATTR_XXLIZER), - [ATTRIBUTE_EXTERN] = (AttributeDomain)~(ATTR_CALL | ATTR_BITSTRUCT | ATTR_MACRO | ATTR_XXLIZER), + [ATTRIBUTE_EXPORT] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | EXPORTED_USER_DEFINED_TYPES, + [ATTRIBUTE_EXTNAME] = (AttributeDomain)~(ATTR_CALL | ATTR_BITSTRUCT | ATTR_DEFINE | ATTR_MACRO | ATTR_XXLIZER), + [ATTRIBUTE_EXTERN] = (AttributeDomain)~(ATTR_CALL | ATTR_BITSTRUCT | ATTR_DEFINE | ATTR_MACRO | ATTR_XXLIZER), [ATTRIBUTE_INLINE] = ATTR_FUNC | ATTR_CALL, [ATTRIBUTE_LITTLEENDIAN] = ATTR_BITSTRUCT, [ATTRIBUTE_MAYDISCARD] = ATTR_FUNC | ATTR_MACRO, @@ -1449,6 +1455,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, [ATTRIBUTE_OVERLAP] = ATTR_BITSTRUCT, [ATTRIBUTE_PACKED] = ATTR_STRUCT | ATTR_UNION, [ATTRIBUTE_PRIORITY] = ATTR_XXLIZER, + [ATTRIBUTE_PRIVATE] = ATTR_FUNC | ATTR_MACRO | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES | ATTR_DEFINE, [ATTRIBUTE_PURE] = ATTR_CALL, [ATTRIBUTE_REFLECT] = ATTR_ENUM, [ATTRIBUTE_SECTION] = ATTR_FUNC | ATTR_CONST | ATTR_GLOBAL, @@ -1505,6 +1512,9 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, break; } break; + case ATTRIBUTE_PRIVATE: + decl->is_private = true; + break; case ATTRIBUTE_TEST: decl->func_decl.attr_test = true; break; @@ -1969,7 +1979,7 @@ static inline MainType sema_find_main_type(SemaContext *context, Signature *sig, static inline Decl *sema_create_synthetic_main(SemaContext *context, Decl *decl, MainType main, bool int_return, bool err_return, bool is_winmain, bool is_wmain) { - Decl *function = decl_new(DECL_FUNC, NULL, decl->span, VISIBLE_PUBLIC); + Decl *function = decl_new(DECL_FUNC, NULL, decl->span); function->is_export = true; function->has_extname = true; function->extname = kw_mainstub; @@ -2112,9 +2122,9 @@ static inline bool sema_analyse_main_function(SemaContext *context, Decl *decl) assert(decl != context->unit->main_function); bool is_winmain = decl->func_decl.attr_winmain; bool is_win32 = platform_target.os == OS_TYPE_WIN32; - if (decl->visibility == VISIBLE_LOCAL) + if (decl->is_private) { - SEMA_ERROR(decl, "A main function may not have local visibility."); + SEMA_ERROR(decl, "A main function may not be private."); return false; } Signature *signature = &decl->func_decl.signature; @@ -2727,14 +2737,14 @@ static Module *module_instantiate_generic(Module *module, Path *path, Expr **par Expr *param = params[i]; if (param->expr_kind != EXPR_TYPEINFO) { - Decl *decl = decl_new_var(param_name, param->span, NULL, VARDECL_CONST, VISIBLE_PUBLIC); + Decl *decl = decl_new_var(param_name, param->span, NULL, VARDECL_CONST); decl->var.init_expr = param; decl->type = param->type; decl->resolve_status = RESOLVE_NOT_DONE; vec_add(first_context->global_decls, decl); continue; } - Decl *decl = decl_new_with_type(param_name, params[i]->span, DECL_TYPEDEF, VISIBLE_PUBLIC); + Decl *decl = decl_new_with_type(param_name, params[i]->span, DECL_TYPEDEF); decl->resolve_status = RESOLVE_DONE; TypeInfo *type_info = param->type_expr; assert(type_info->resolve_status == RESOLVE_DONE); @@ -2967,6 +2977,8 @@ static inline bool sema_analyse_attribute_decl(SemaContext *c, Decl *decl) static inline bool sema_analyse_define(SemaContext *c, Decl *decl) { + if (!sema_analyse_attributes(c, decl, decl->attributes, ATTR_DEFINE)) return decl_poison(decl); + // 1. The plain define if (decl->define_decl.define_kind == DEFINE_IDENT_ALIAS) { diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index 02f3feec0..353f30046 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -151,7 +151,7 @@ static Decl *sema_find_decl_in_imports(Decl **imports, NameResolve *name_resolve if (!found) continue; // If we found something private but we don't import privately? - if (found->visibility <= VISIBLE_MODULE && !import->import.private && !decl) + if (found->is_private && !import->import.private && !decl) { // Register this as a possible private decl. name_resolve->private_decl = found; @@ -594,7 +594,7 @@ Decl *sema_resolve_method_in_module(Module *module, Type *actual_type, const cha if (module->is_generic) return NULL; Decl *found = sema_find_extension_method_in_module(module->private_method_extensions, actual_type, method_name); // The found one might not be visible - if (found && search_type < METHOD_SEARCH_CURRENT && found->visibility < VISIBLE_PUBLIC) + if (found && search_type < METHOD_SEARCH_CURRENT && found->is_private) { *private_found = found; found = NULL; diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index bd99815b7..2d71a1c4c 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -368,7 +368,7 @@ void sema_analysis_pass_ct_echo(Module *module) static inline bool analyse_func_body(SemaContext *context, Decl *decl) { if (!decl->func_decl.body) return true; - if (decl->visibility == VISIBLE_EXTERN) + if (decl->is_extern) { SEMA_ERROR(decl, "'extern' functions should never have a body."); return decl_poison(decl); diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index ad5a2829e..fe8869800 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -579,7 +579,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr) } // 4d. A new declaration is created. - Decl *decl = decl_new_var(ident->identifier_expr.ident, ident->span, var_type, VARDECL_LOCAL, VISIBLE_LOCAL); + Decl *decl = decl_new_var(ident->identifier_expr.ident, ident->span, var_type, VARDECL_LOCAL); // 4e. Analyse it if (!sema_analyse_var_decl(context, decl, true)) return false; @@ -681,7 +681,7 @@ static inline bool sema_analyse_catch_unwrap(SemaContext *context, Expr *expr) } // 4d. A new declaration is created. - Decl *decl = decl_new_var(ident->identifier_expr.ident, ident->span, type, VARDECL_LOCAL, VISIBLE_LOCAL); + Decl *decl = decl_new_var(ident->identifier_expr.ident, ident->span, type, VARDECL_LOCAL); decl->var.no_init = true; // 4e. Analyse it @@ -2072,7 +2072,7 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc Decl *new_var = decl_new_var(variant->new_ident, variant->span, type_info_new_base(variant->is_deref ? real_type->pointer : real_type, variant->span), - VARDECL_LOCAL, VISIBLE_LOCAL); + VARDECL_LOCAL); Expr *var_result = expr_variable(var_holder); if (!cast(var_result, real_type)) return false; if (variant->is_deref) @@ -2089,7 +2089,7 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc Type *type = type_get_ptr(stmt->case_stmt.expr->const_expr.typeid); Decl *alias = decl_new_var(var_holder->name, var_holder->span, type_info_new_base(type, stmt->case_stmt.expr->span), - VARDECL_LOCAL, VISIBLE_LOCAL); + VARDECL_LOCAL); Expr *ident_converted = expr_variable(var_holder); if (!cast(ident_converted, type)) return false; alias->var.init_expr = ident_converted; @@ -2304,11 +2304,11 @@ static inline bool sema_analyse_ct_foreach_stmt(SemaContext *context, Ast *state AstId start = 0; if (index_name) { - index = decl_new_var(index_name, statement->ct_foreach_stmt.index_span, NULL, VARDECL_LOCAL_CT, VISIBLE_LOCAL); + index = decl_new_var(index_name, statement->ct_foreach_stmt.index_span, NULL, VARDECL_LOCAL_CT); index->type = type_int; if (!sema_add_local(context, index)) goto FAILED; } - Decl *value = decl_new_var(statement->ct_foreach_stmt.value_name, statement->ct_foreach_stmt.value_span, NULL, VARDECL_LOCAL_CT, VISIBLE_LOCAL); + Decl *value = decl_new_var(statement->ct_foreach_stmt.value_name, statement->ct_foreach_stmt.value_span, NULL, VARDECL_LOCAL_CT); if (!sema_add_local(context, value)) goto FAILED; // Get the body Ast *body = astptr(statement->ct_foreach_stmt.body); diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index 77cff493d..3caa0ada6 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -198,7 +198,7 @@ static void register_generic_decls(CompilationUnit *unit, Decl **decls) break; } htable_set(&unit->module->symbols, (void *)decl->name, decl); - if (decl->visibility == VISIBLE_PUBLIC) global_context_add_generic_decl(decl); + if (!decl->is_private) global_context_add_generic_decl(decl); } } diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 924b25a3d..20baacc01 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -312,6 +312,7 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_OVERLAP] = KW_DEF("@overlap"); attribute_list[ATTRIBUTE_PACKED] = KW_DEF("@packed"); attribute_list[ATTRIBUTE_PRIORITY] = KW_DEF("@priority"); + attribute_list[ATTRIBUTE_PRIVATE] = KW_DEF("@private"); attribute_list[ATTRIBUTE_PURE] = kw_at_pure; attribute_list[ATTRIBUTE_REFLECT] = KW_DEF("@reflect"); attribute_list[ATTRIBUTE_SECTION] = KW_DEF("@section"); diff --git a/src/version.h b/src/version.h index cfc5794f1..c2080c0c4 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.4.59" \ No newline at end of file +#define COMPILER_VERSION "0.4.60" \ No newline at end of file diff --git a/test/test_suite/arrays/array_struct.c3t b/test/test_suite/arrays/array_struct.c3t index 95a64f13f..ad1ef0df0 100644 --- a/test/test_suite/arrays/array_struct.c3t +++ b/test/test_suite/arrays/array_struct.c3t @@ -6,7 +6,7 @@ struct Foo int x, y; } -private Foo[10] array; +Foo[10] array @private; // #expect: test.ll diff --git a/test/test_suite/arrays/complex_array_const.c3t b/test/test_suite/arrays/complex_array_const.c3t index af690fbd3..2386c21c9 100644 --- a/test/test_suite/arrays/complex_array_const.c3t +++ b/test/test_suite/arrays/complex_array_const.c3t @@ -8,7 +8,7 @@ struct Connection long length; } -private Connection[3] link +Connection[3] link @private = { {1, "link1", 10}, {2, "link2", 20}, {3, "link3", 30} }; diff --git a/test/test_suite/attributes/attribute_visibility.c3t b/test/test_suite/attributes/attribute_visibility.c3t index adfa7b9b9..cab75cafe 100644 --- a/test/test_suite/attributes/attribute_visibility.c3t +++ b/test/test_suite/attributes/attribute_visibility.c3t @@ -1,12 +1,12 @@ // #target: macos-x64 module test; -private const int FOO = 4; -define @Align(x) = @align(x * FOO); +const int FOO @private = 4; +define @Align(x) = { @align(x * FOO) }; module test2; import test; int black @Align(16) = 123; -// #expect: test2.ll +/* #expect: test2.ll @test2_black = local_unnamed_addr global i32 123, align 64 \ No newline at end of file diff --git a/test/test_suite/attributes/recursive_attributes.c3 b/test/test_suite/attributes/recursive_attributes.c3 index f3e6a9a0b..d2082850d 100644 --- a/test/test_suite/attributes/recursive_attributes.c3 +++ b/test/test_suite/attributes/recursive_attributes.c3 @@ -1,8 +1,8 @@ module test; -define @Align(y) = @Align16(y / 2); -define @Align16(x) = @align(4), @Align(8 * x); // #error: Recursive declaration of attribute -define @Test = @noinline; +define @Align(y) = { @Align16(y / 2) }; +define @Align16(x) = { @align(4) @Align(8 * x) }; // #error: Recursive declaration of attribute +define @Test = { @noinline }; struct Foo { int z; diff --git a/test/test_suite/attributes/user_defined_attributes.c3t b/test/test_suite/attributes/user_defined_attributes.c3t index 1e120511e..ffb6da25d 100644 --- a/test/test_suite/attributes/user_defined_attributes.c3t +++ b/test/test_suite/attributes/user_defined_attributes.c3t @@ -2,12 +2,12 @@ module test; -define @Foo = @noreturn, @weak; +define @Foo = { @noreturn @weak }; -define @Align(y) = @align(y); -define @Align16(x) = @Align(8 * x), @align(1024); -define @Test = @noinline; -define @TestZero; +define @Align(y) = { @align(y) }; +define @Align16(x) @private = { @Align(8 * x) @align(1024) }; +define @Test = { @noinline }; +define @TestZero = { }; struct Foo { int z; diff --git a/test/test_suite/clang/2002-07.c3t b/test/test_suite/clang/2002-07.c3t index 914d373bb..b94b25cf8 100644 --- a/test/test_suite/clang/2002-07.c3t +++ b/test/test_suite/clang/2002-07.c3t @@ -85,9 +85,9 @@ fn void* memset_impl(void* dstpp, int c, uint len) // TEST problem with signed/unsigned versions of the same constants being shared // incorrectly! -private char* temp; -private int remaining; -private fn char* localmalloc(int size) { +char* temp @private; +int remaining @private; +fn char* localmalloc(int size) @private { char* blah; if (size>remaining) @@ -160,7 +160,7 @@ fn char smallArgs(char w, char x, char y, char z) { return smallArgs2(w-1, x+1, y, z, w); } -private fn int f0(Quad q, int i) { /* Pass Q by value */ +fn int f0(Quad q, int i) @private { /* Pass Q by value */ Quad r @noinit; if (i) r.ss = q.ss; q.ssp = &r.ss; diff --git a/test/test_suite/constants/constants.c3t b/test/test_suite/constants/constants.c3t index 9f4fdb99b..e3ed81a6c 100644 --- a/test/test_suite/constants/constants.c3t +++ b/test/test_suite/constants/constants.c3t @@ -1,15 +1,15 @@ -private const char AA = ~(char)(0); +const char AA @private = ~(char)(0); const char BB = 200 ; -private const uint CC = ~(uint)(0); -private const uint DD = FOO; +const uint CC @private = ~(uint)(0); +const uint DD @private = FOO; -private const FOO = ~(uint)(0); +const FOO @private = ~(uint)(0); -private uint x = AA; -private uint z = CC; -private char w = (char)(FOO); -private ushort v = (ushort)(FOO); -private uint z2 = DD; +uint x @private = AA; +uint z @private = CC; +char w @private = (char)(FOO); +ushort v @private = (ushort)(FOO); +uint z2 @private = DD; fn void test() { diff --git a/test/test_suite/debug_symbols/constants.c3t b/test/test_suite/debug_symbols/constants.c3t index c90334e96..d1b3062a8 100644 --- a/test/test_suite/debug_symbols/constants.c3t +++ b/test/test_suite/debug_symbols/constants.c3t @@ -1,9 +1,9 @@ // #target: macos-x64 // #debuginfo: yes -private const char AA = 1; +const char AA @private = 1; const char BB = 200 ; -private const uint CC = ~(uint)(0); -private const FOO = ~(uint)(0); +const uint CC @private = ~(uint)(0); +const FOO @private = ~(uint)(0); /* #expect: constants.ll diff --git a/test/test_suite/expressions/bool_conversions.c3t b/test/test_suite/expressions/bool_conversions.c3t index 928256869..10e40721c 100644 --- a/test/test_suite/expressions/bool_conversions.c3t +++ b/test/test_suite/expressions/bool_conversions.c3t @@ -1,6 +1,6 @@ // #target: macos-x64 -private fn bool f0_0(void* a0) { return (bool)a0; } +fn bool f0_0(void* a0) @private { return (bool)a0; } fn int f0() { return (int)f0_0((void*)0x2); } diff --git a/test/test_suite/import/access_other_module.c3t b/test/test_suite/import/access_other_module.c3t index afc52275e..02716f8a2 100644 --- a/test/test_suite/import/access_other_module.c3t +++ b/test/test_suite/import/access_other_module.c3t @@ -9,7 +9,7 @@ fn void main() /* #expect: foo.ll -@libc_EXIT_SUCCESS = external global i32, align 4 +@libc_EXIT_SUCCESS = external constant i32, align 4 define void @foo_main() #0 { entry: diff --git a/test/test_suite/initializer_lists/fasta.c3t b/test/test_suite/initializer_lists/fasta.c3t index ec2c582e5..8e7096507 100644 --- a/test/test_suite/initializer_lists/fasta.c3t +++ b/test/test_suite/initializer_lists/fasta.c3t @@ -14,7 +14,7 @@ fn float fasta_rand(float maxval) return maxval * seed / IM; } -private char[] alu = +char[] alu @private = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" diff --git a/test/test_suite/lambda/nested_lambda_def.c3t b/test/test_suite/lambda/nested_lambda_def.c3t index 29dff3356..3a3d239cb 100644 --- a/test/test_suite/lambda/nested_lambda_def.c3t +++ b/test/test_suite/lambda/nested_lambda_def.c3t @@ -17,7 +17,7 @@ module foo; import bar; import std::io; -private int xz = 0; +int xz @private = 0; macro Callback get_callback() diff --git a/test/test_suite/macros/hash_ident.c3 b/test/test_suite/macros/hash_ident.c3 index 4dfa36bd1..1244c7918 100644 --- a/test/test_suite/macros/hash_ident.c3 +++ b/test/test_suite/macros/hash_ident.c3 @@ -4,7 +4,7 @@ macro int @cofefe(#a) return #a + #a; } -private int abc = 1; +int abc @private = 1; fn int xx() { diff --git a/test/test_suite/macros/macro_import_res_private.c3t b/test/test_suite/macros/macro_import_res_private.c3t index 95bfa9cd3..377fe02fe 100644 --- a/test/test_suite/macros/macro_import_res_private.c3t +++ b/test/test_suite/macros/macro_import_res_private.c3t @@ -1,6 +1,6 @@ // #target: macos-x64 module foo; -private fn void foo1() +fn void foo1() @private {} module bar; diff --git a/test/test_suite/macros/macro_resolution.c3 b/test/test_suite/macros/macro_resolution.c3 index 37f80b138..0776d1441 100644 --- a/test/test_suite/macros/macro_resolution.c3 +++ b/test/test_suite/macros/macro_resolution.c3 @@ -10,7 +10,7 @@ fn void run2() bar::test2(); } -private fn void tester() {} +fn void tester() @private {} module bar; macro test() diff --git a/test/test_suite/pointers/const_pointer.c3t b/test/test_suite/pointers/const_pointer.c3t index b8feacb81..cb39fb26e 100644 --- a/test/test_suite/pointers/const_pointer.c3t +++ b/test/test_suite/pointers/const_pointer.c3t @@ -2,11 +2,11 @@ module const_pointer; -private double foo = 17; -private double bar = 12.0; -private float xx = 12.0; +double foo @private = 17; +double bar @private = 12.0; +float xx @private = 12.0; -private void*[3] data = { &foo, &bar, &xx }; +void*[3] data @private = { &foo, &bar, &xx }; /* #expect: const_pointer.ll diff --git a/test/test_suite/struct/simple_struct.c3t b/test/test_suite/struct/simple_struct.c3t index fe64e4641..e7610fc32 100644 --- a/test/test_suite/struct/simple_struct.c3t +++ b/test/test_suite/struct/simple_struct.c3t @@ -1,6 +1,6 @@ module test; -private Foo a; +Foo a @private; struct Foo { diff --git a/test/test_suite/struct/struct_const_construct_simple.c3t b/test/test_suite/struct/struct_const_construct_simple.c3t index 0f3192eb8..6b709f0dd 100644 --- a/test/test_suite/struct/struct_const_construct_simple.c3t +++ b/test/test_suite/struct/struct_const_construct_simple.c3t @@ -7,16 +7,16 @@ struct Foo long bar; } -private usz x = Foo.sizeof; +usz x @private = Foo.sizeof; -private Foo foo1 = { 1, 2 }; -private Foo foo2 = { .foo = 2 }; -private Foo foo3 = { .bar = 3 }; -private Foo foo4 = { .bar = 4, .foo = 4, .bar = 1 }; -private Foo foo5 = {}; -private Foo foo6; -private const Foo FOO7 = { 1, 2 }; -private Foo foo8 = FOO7; +Foo foo1 @private = { 1, 2 }; +Foo foo2 @private = { .foo = 2 }; +Foo foo3 @private = { .bar = 3 }; +Foo foo4 @private = { .bar = 4, .foo = 4, .bar = 1 }; +Foo foo5 @private = {}; +Foo foo6 @private; +const Foo FOO7 @private = { 1, 2 }; +Foo foo8 @private = FOO7; /* #expect: structo.ll diff --git a/test/test_suite/union/union_codegen_const.c3t b/test/test_suite/union/union_codegen_const.c3t index 60582734b..f99be8c5c 100644 --- a/test/test_suite/union/union_codegen_const.c3t +++ b/test/test_suite/union/union_codegen_const.c3t @@ -6,9 +6,9 @@ union Foo double b; } -private Foo f = { .a = 23 }; -private Foo g = { .b = 2.3 }; -private Foo h = { .a = 23, .b = 2.3 }; +Foo f @private = { .a = 23 }; +Foo g @private = { .b = 2.3 }; +Foo h @private = { .a = 23, .b = 2.3 }; Foo i = { .b = 2.3, .a = 23 }; // #expect: test.ll @@ -17,4 +17,3 @@ Foo i = { .b = 2.3, .a = 23 }; @test_g = protected unnamed_addr global %Foo { double 2.300000e+00 }, align 8 @test_h = protected unnamed_addr global %Foo { double 2.300000e+00 }, align 8 @test_i = local_unnamed_addr global { i32, [4 x i8] } { i32 23, [4 x i8] undef }, align 8 - diff --git a/test/test_suite/visibility/ambiguous_var.c3t b/test/test_suite/visibility/ambiguous_var.c3t index dfad51ace..1220ae9c5 100644 --- a/test/test_suite/visibility/ambiguous_var.c3t +++ b/test/test_suite/visibility/ambiguous_var.c3t @@ -17,8 +17,8 @@ import bar; int a; -private fn void test2() -{ +fn void test2() + @private{ int c = a; // This is fine. c = foo::b; c = bar::b; diff --git a/test/test_suite/visibility/no_shared_imports.c3t b/test/test_suite/visibility/no_shared_imports.c3t index 420d4410c..28c0e8e42 100644 --- a/test/test_suite/visibility/no_shared_imports.c3t +++ b/test/test_suite/visibility/no_shared_imports.c3t @@ -11,13 +11,13 @@ fn void runBar() module baz; import private bar; -private fn void visible() -{ +fn void visible() + @private{ bar::barFunc(); } // #file: file3.c3 module bar; -private fn void barFunc() -{} \ No newline at end of file +fn void barFunc() + @private{} \ No newline at end of file diff --git a/test/test_suite/visibility/not_visible.c3t b/test/test_suite/visibility/not_visible.c3t index 30aa271fa..860d0c948 100644 --- a/test/test_suite/visibility/not_visible.c3t +++ b/test/test_suite/visibility/not_visible.c3t @@ -10,7 +10,7 @@ fn void runBar() // #file: file2.c3 module bar; -private fn void notVisible() -{ +fn void notVisible() + @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 32360a4c6..2e23b9a65 100644 --- a/test/test_suite/visibility/private_import.c3 +++ b/test/test_suite/visibility/private_import.c3 @@ -1,6 +1,6 @@ module foo; -private fn void hidden() +fn void hidden() @private { } diff --git a/test/test_suite/visibility/shared_module.c3t b/test/test_suite/visibility/shared_module.c3t index 3895bec2a..dc1adad95 100644 --- a/test/test_suite/visibility/shared_module.c3t +++ b/test/test_suite/visibility/shared_module.c3t @@ -9,7 +9,7 @@ fn void runBar() // #file: file2.c3 module baz; -private fn void visible() -{ +fn void visible() + @private{ } \ No newline at end of file