From dc52478c09d7e28887df035fc970f056cea66b05 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 21 Feb 2026 21:10:08 +0100 Subject: [PATCH] - Warn on use of visibility modifiers on methods. #2962 --- lib/std/collections/hashmap.c3 | 48 +-- lib/std/collections/hashset.c3 | 48 +-- lib/std/collections/interfacelist.c3 | 24 +- lib/std/collections/linked_blockingqueue.c3 | 16 +- lib/std/collections/linked_hashmap.c3 | 42 +- lib/std/collections/linked_hashset.c3 | 40 +- lib/std/collections/linkedlist.c3 | 44 +-- lib/std/collections/list.c3 | 36 +- lib/std/collections/object.c3 | 14 +- lib/std/compression/deflate.c3 | 34 +- .../core/allocators/backed_arena_allocator.c3 | 10 +- lib/std/core/allocators/dynamic_arena.c3 | 112 +++--- lib/std/core/allocators/heap_allocator.c3 | 36 +- lib/std/core/allocators/temp_allocator.c3 | 73 ++-- lib/std/core/dstring.c3 | 2 +- lib/std/core/mem_allocator.c3 | 49 +++ lib/std/core/mem_mempool.c3 | 22 +- lib/std/core/os/mem_vm.c3 | 4 +- lib/std/crypto/chacha20.c3 | 6 +- lib/std/crypto/ed25519.c3 | 4 +- lib/std/experimental/FrameScheduler.c3 | 2 +- lib/std/hash/blake2.c3 | 100 ++--- lib/std/hash/blake3.c3 | 28 +- lib/std/hash/gost/streebog.c3 | 4 +- lib/std/hash/poly1305.c3 | 8 +- lib/std/hash/sha256.c3 | 16 +- lib/std/hash/siphash.c3 | 8 +- lib/std/hash/whirlpool/whirlpool.c3 | 10 +- lib/std/io/formatter.c3 | 263 ++---------- lib/std/io/formatter_private.c3 | 374 ++++++++++++++---- lib/std/io/io.c3 | 2 +- lib/std/io/stream/buffer.c3 | 14 +- lib/std/math/bigint.c3 | 53 +-- lib/std/threads/os/thread_win32.c3 | 6 +- releasenotes.md | 1 + src/build/build.h | 1 + src/build/build_options.c | 6 + src/build/builder.c | 4 + src/compiler/parse_expr.c | 2 +- src/compiler/parse_global.c | 74 +++- src/compiler/parser_internal.h | 2 +- src/compiler/sema_decls.c | 2 + .../methods/access_private_method.c3 | 4 +- .../methods/extending_with_visibility.c3 | 35 -- .../methods/extending_with_visibility_fail.c3 | 37 -- .../extending_with_visibility_fail_private.c3 | 37 -- test/test_suite/methods/method_from_var.c3 | 4 +- .../switch/switch_in_defer_macro.c3t | 34 +- test/unit/regression/operator_overload.c3 | 2 +- 49 files changed, 907 insertions(+), 890 deletions(-) delete mode 100644 test/test_suite/methods/extending_with_visibility.c3 delete mode 100644 test/test_suite/methods/extending_with_visibility_fail.c3 delete mode 100644 test/test_suite/methods/extending_with_visibility_fail_private.c3 diff --git a/lib/std/collections/hashmap.c3 b/lib/std/collections/hashmap.c3 index 1254ec941..68a742f1e 100644 --- a/lib/std/collections/hashmap.c3 +++ b/lib/std/collections/hashmap.c3 @@ -150,7 +150,7 @@ fn bool HashMap.is_initialized(&map) fn HashMap* HashMap.init_from_map(&self, Allocator allocator, HashMap* other_map) { self.init(allocator, other_map.table.len, other_map.load_factor); - self.put_all_for_create(other_map); + hashmap_put_all_for_create(self, other_map); return self; } @@ -233,7 +233,7 @@ macro Value HashMap.@get_or_set(&map, Key key, Value #expr) if (e.hash == hash && equals(key, e.key)) return e.value; } Value val = #expr; - map.add_entry(hash, key, val, index); + hashmap_add_entry(map, hash, key, val, index); return val; } @@ -269,13 +269,13 @@ fn bool HashMap.set(&map, Key key, Value value) @operator([]=) return true; } } - map.add_entry(hash, key, value, index); + hashmap_add_entry(map, hash, key, value, index); return false; } fn void? HashMap.remove(&map, Key key) @maydiscard { - if (!map.remove_entry_for_key(key)) return NOT_FOUND~; + if (!hashmap_remove_entry_for_key(map, key)) return NOT_FOUND~; } fn void HashMap.clear(&map) @@ -290,9 +290,9 @@ fn void HashMap.clear(&map) { Entry *to_delete = next; next = next.next; - map.free_entry(to_delete); + hashmap_free_entry(map, to_delete); } - map.free_entry(entry); + hashmap_free_entry(map, entry); *entry_ref = null; } map.count = 0; @@ -302,7 +302,7 @@ fn void HashMap.free(&map) { if (!map.is_initialized()) return; map.clear(); - map.free_internal(map.table.ptr); + hashmap_free_internal(map, map.table.ptr); map.table = {}; } @@ -402,7 +402,7 @@ fn HashMapKeyIterator HashMap.key_iter(&self) // --- private methods -fn void HashMap.add_entry(&map, uint hash, Key key, Value value, uint bucket_index) @private +fn void hashmap_add_entry(HashMap* map, uint hash, Key key, Value value, uint bucket_index) @private { $if COPY_KEYS: key = key.copy(map.allocator); @@ -411,11 +411,11 @@ fn void HashMap.add_entry(&map, uint hash, Key key, Value value, uint bucket_ind map.table[bucket_index] = entry; if (map.count++ >= map.threshold) { - map.resize(map.table.len * 2); + hashmap_resize(map, map.table.len * 2); } } -fn void HashMap.resize(&map, uint new_capacity) @private +fn void hashmap_resize(HashMap* map, uint new_capacity) @private { Entry*[] old_table = map.table; uint old_capacity = old_table.len; @@ -425,9 +425,9 @@ fn void HashMap.resize(&map, uint new_capacity) @private return; } Entry*[] new_table = allocator::new_array(map.allocator, Entry*, new_capacity); - map.transfer(new_table); + hashmap_transfer(map, new_table); map.table = new_table; - map.free_internal(old_table.ptr); + hashmap_free_internal(map, old_table.ptr); map.threshold = (uint)(new_capacity * map.load_factor); } @@ -443,7 +443,7 @@ fn usz? HashMap.to_format(&self, Formatter* f) @dynamic return len + f.print(" }"); } -fn void HashMap.transfer(&map, Entry*[] new_table) @private +fn void hashmap_transfer(HashMap* map, Entry*[] new_table) @private { Entry*[] src = map.table; uint new_capacity = new_table.len; @@ -462,20 +462,20 @@ fn void HashMap.transfer(&map, Entry*[] new_table) @private } } -fn void HashMap.put_all_for_create(&map, HashMap* other_map) @private +fn void hashmap_put_all_for_create(HashMap* map, HashMap* other_map) @private { if (!other_map.count) return; foreach (Entry *e : other_map.table) { while (e) { - map.put_for_create(e.key, e.value); + hashmap_put_for_create(map, e.key, e.value); e = e.next; } } } -fn void HashMap.put_for_create(&map, Key key, Value value) @private +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); @@ -487,15 +487,15 @@ fn void HashMap.put_for_create(&map, Key key, Value value) @private return; } } - map.create_entry(hash, key, value, i); + hashmap_create_entry(map, hash, key, value, i); } -fn void HashMap.free_internal(&map, void* ptr) @inline @private +fn void hashmap_free_internal(HashMap* map, void* ptr) @inline @private { allocator::free(map.allocator, ptr); } -fn bool HashMap.remove_entry_for_key(&map, Key key) @private +fn bool hashmap_remove_entry_for_key(HashMap* map, Key key) @private { if (!map.count) return false; uint hash = rehash(key.hash()); @@ -516,7 +516,7 @@ fn bool HashMap.remove_entry_for_key(&map, Key key) @private { prev.next = next; } - map.free_entry(e); + hashmap_free_entry(map, e); return true; } prev = e; @@ -525,7 +525,7 @@ fn bool HashMap.remove_entry_for_key(&map, Key key) @private return false; } -fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_index) @private +fn void hashmap_create_entry(HashMap* map, uint hash, Key key, Value value, int bucket_index) @private { Entry *e = map.table[bucket_index]; $if COPY_KEYS: @@ -536,12 +536,12 @@ fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_i map.count++; } -fn void HashMap.free_entry(&self, Entry *entry) @local +fn void hashmap_free_entry(HashMap* map, Entry *entry) @local { $if COPY_KEYS: - allocator::free(self.allocator, entry.key); + allocator::free(map.allocator, entry.key); $endif - self.free_internal(entry); + hashmap_free_internal(map, entry); } diff --git a/lib/std/collections/hashset.c3 b/lib/std/collections/hashset.c3 index 19eefb4e9..85753510d 100644 --- a/lib/std/collections/hashset.c3 +++ b/lib/std/collections/hashset.c3 @@ -135,7 +135,7 @@ fn bool HashSet.is_initialized(&set) fn HashSet* HashSet.init_from_set(&self, Allocator allocator, HashSet* other_set) { self.init(allocator, other_set.table.len, other_set.load_factor); - self.put_all_for_create(other_set); + hashset_put_all_for_create(self, other_set); return self; } @@ -213,7 +213,7 @@ fn bool HashSet.add(&set, Value value) { if (e.hash == hash && equals(value, e.value)) return false; } - set.add_entry(hash, value, index); + hashset_add_entry(set, hash, value, index); return true; } @@ -258,7 +258,7 @@ fn bool HashSet.contains(&set, Value value) *> fn void? HashSet.remove(&set, Value value) @maydiscard { - if (!set.remove_entry_for_value(value)) return NOT_FOUND~; + if (!hashset_remove_entry_for_value(set, value)) return NOT_FOUND~; } fn usz HashSet.remove_all(&set, Value[] values) @@ -266,7 +266,7 @@ fn usz HashSet.remove_all(&set, Value[] values) usz total; foreach (v : values) { - if (set.remove_entry_for_value(v)) total++; + if (hashset_remove_entry_for_value(set, v)) total++; } return total; } @@ -279,7 +279,7 @@ fn usz HashSet.remove_all_from(&set, HashSet* other) usz total; other.@each(;Value val) { - if (set.remove_entry_for_value(val)) total++; + if (hashset_remove_entry_for_value(set, val)) total++; }; return total; } @@ -291,7 +291,7 @@ fn void HashSet.free(&set) { if (!set.is_initialized()) return; set.clear(); - set.free_internal(set.table.ptr); + hashset_free_internal(set, set.table.ptr); *set = {}; } @@ -314,10 +314,10 @@ fn void HashSet.clear(&set) { Entry *to_delete = next; next = next.next; - set.free_entry(to_delete); + hashset_free_entry(set, to_delete); } - set.free_entry(entry); + hashset_free_entry(set, entry); *entry_ref = null; } set.count = 0; @@ -327,7 +327,7 @@ fn void HashSet.reserve(&set, usz capacity) { if (capacity > set.threshold) { - set.resize(math::next_power_of_2(capacity)); + hashset_resize(set, math::next_power_of_2(capacity)); } } @@ -464,17 +464,17 @@ fn bool HashSet.is_subset(&self, HashSet* other) // --- private methods -fn void HashSet.add_entry(&set, uint hash, Value value, uint bucket_index) @private +fn void hashset_add_entry(HashSet* set, uint hash, Value value, uint bucket_index) @private { Entry* entry = allocator::new(set.allocator, Entry, { .hash = hash, .value = value, .next = set.table[bucket_index] }); set.table[bucket_index] = entry; if (set.count++ >= set.threshold) { - set.resize(set.table.len * 2); + hashset_resize(set, set.table.len * 2); } } -fn void HashSet.resize(&self, usz new_capacity) @private +fn void hashset_resize(HashSet* self, usz new_capacity) @private { Entry*[] old_table = self.table; usz old_capacity = old_table.len; @@ -484,9 +484,9 @@ fn void HashSet.resize(&self, usz new_capacity) @private return; } Entry*[] new_table = allocator::new_array(self.allocator, Entry*, new_capacity); - self.transfer(new_table); + hashset_transfer(self, new_table); self.table = new_table; - self.free_internal(old_table.ptr); + hashset_free_internal(self, old_table.ptr); self.threshold = (uint)(new_capacity * self.load_factor); } @@ -502,7 +502,7 @@ fn usz? HashSet.to_format(&self, Formatter* f) @dynamic return len + f.print(" }"); } -fn void HashSet.transfer(&self, Entry*[] new_table) @private +fn void hashset_transfer(HashSet* self, Entry*[] new_table) @private { Entry*[] src = self.table; uint new_capacity = new_table.len; @@ -521,20 +521,20 @@ fn void HashSet.transfer(&self, Entry*[] new_table) @private } } -fn void HashSet.put_all_for_create(&set, HashSet* other_set) @private +fn void hashset_put_all_for_create(HashSet* set, HashSet* other_set) @private { if (!other_set.count) return; foreach (Entry *e : other_set.table) { while (e) { - set.put_for_create(e.value); + hashset_put_for_create(set, e.value); e = e.next; } } } -fn void HashSet.put_for_create(&set, Value value) @private +fn void hashset_put_for_create(HashSet* set, Value value) @private { uint hash = rehash(value.hash()); uint i = index_for(hash, set.table.len); @@ -546,15 +546,15 @@ fn void HashSet.put_for_create(&set, Value value) @private return; } } - set.create_entry(hash, value, i); + hashset_create_entry(set, hash, value, i); } -fn void HashSet.free_internal(&self, void* ptr) @inline @private +fn void hashset_free_internal(HashSet* self, void* ptr) @inline @private { allocator::free(self.allocator, ptr); } -fn void HashSet.create_entry(&set, uint hash, Value value, int bucket_index) @private +fn void hashset_create_entry(HashSet* set, uint hash, Value value, int bucket_index) @private { Entry* entry = allocator::new(set.allocator, Entry, { .hash = hash, @@ -569,7 +569,7 @@ fn void HashSet.create_entry(&set, uint hash, Value value, int bucket_index) @pr Removes the entry for the specified value if present @return "true if found and removed, false otherwise" *> -fn bool HashSet.remove_entry_for_value(&set, Value value) @private +fn bool hashset_remove_entry_for_value(HashSet* set, Value value) @private { if (!set.count) return false; uint hash = rehash(value.hash()); @@ -590,7 +590,7 @@ fn bool HashSet.remove_entry_for_value(&set, Value value) @private { prev.next = next; } - set.free_entry(e); + hashset_free_entry(set, e); return true; } prev = e; @@ -600,7 +600,7 @@ fn bool HashSet.remove_entry_for_value(&set, Value value) @private return false; } -fn void HashSet.free_entry(&set, Entry *entry) @private +fn void hashset_free_entry(HashSet* set, Entry *entry) @private { allocator::free(set.allocator, entry); } diff --git a/lib/std/collections/interfacelist.c3 b/lib/std/collections/interfacelist.c3 index 1f6212988..79e3d4f3a 100644 --- a/lib/std/collections/interfacelist.c3 +++ b/lib/std/collections/interfacelist.c3 @@ -73,7 +73,7 @@ fn bool InterfaceList.is_initialized(&self) @inline => self.allocator != null; macro void InterfaceList.push(&self, element) { if (!self.allocator) self.allocator = tmem; - self._append(allocator::clone(self.allocator, element)); + interfacelist_append(self, allocator::clone(self.allocator, element)); } <* @@ -381,7 +381,7 @@ fn usz? InterfaceList.to_format(&self, Formatter* formatter) @dynamic *> fn usz InterfaceList.remove_if(&self, InterfacePredicate filter) { - return self._remove_if(filter, false); + return interfacelist_remove_if(self, filter, false); } <* @@ -392,7 +392,7 @@ fn usz InterfaceList.remove_if(&self, InterfacePredicate filter) *> fn usz InterfaceList.retain_if(&self, InterfacePredicate selection) { - return self._remove_if(selection, true); + return interfacelist_remove_if(self, selection, true); } <* @@ -404,7 +404,7 @@ fn usz InterfaceList.retain_if(&self, InterfacePredicate selection) *> fn usz InterfaceList.remove_using_test(&self, InterfaceTest filter, Type context) { - return self._remove_using_test(filter, false, context); + return interfacelist_remove_using_test(self, filter, false, context); } <* @@ -416,7 +416,7 @@ fn usz InterfaceList.remove_using_test(&self, InterfaceTest filter, Type context *> fn usz InterfaceList.retain_using_test(&self, InterfaceTest selection, Type context) { - return self._remove_using_test(selection, true, context); + return interfacelist_remove_using_test(self, selection, true, context); } <* @@ -455,7 +455,7 @@ macro void InterfaceList.set(&self, usz index, value) // -- private -fn void InterfaceList.ensure_capacity(&self, usz added = 1) @inline @private +fn void interfacelist_ensure_capacity(InterfaceList* self, usz added = 1) @inline @private { usz new_size = self.size + added; if (self.capacity >= new_size) return; @@ -466,18 +466,18 @@ fn void InterfaceList.ensure_capacity(&self, usz added = 1) @inline @private self.reserve(new_capacity); } -fn void InterfaceList._append(&self, Type element) @local +fn void interfacelist_append(InterfaceList* self, Type element) @local { - self.ensure_capacity(); + interfacelist_ensure_capacity(self); self.entries[self.size++] = element; } <* @require index < self.size *> -fn void InterfaceList._insert_at(&self, usz index, Type value) @local +fn void interfacelist_insert_at(InterfaceList* self, usz index, Type value) @local { - self.ensure_capacity(); + interfacelist_ensure_capacity(self); for (usz i = self.size; i > index; i--) { self.entries[i] = self.entries[i - 1]; @@ -486,7 +486,7 @@ fn void InterfaceList._insert_at(&self, usz index, Type value) @local self.entries[index] = value; } -macro usz InterfaceList._remove_using_test(&self, InterfaceTest filter, bool $invert, ctx) @local +macro usz interfacelist_remove_using_test(InterfaceList* self, InterfaceTest filter, bool $invert, ctx) @local { usz size = self.size; for (usz i = size, usz k = size; k > 0; k = i) @@ -512,7 +512,7 @@ macro usz InterfaceList._remove_using_test(&self, InterfaceTest filter, bool $in return size - self.size; } -macro usz InterfaceList._remove_if(&self, InterfacePredicate filter, bool $invert) @local +macro usz interfacelist_remove_if(InterfaceList* self, InterfacePredicate filter, bool $invert) @local { usz size = self.size; for (usz i = size, usz k = size; k > 0; k = i) diff --git a/lib/std/collections/linked_blockingqueue.c3 b/lib/std/collections/linked_blockingqueue.c3 index d9b273b85..4b9a5e6ce 100644 --- a/lib/std/collections/linked_blockingqueue.c3 +++ b/lib/std/collections/linked_blockingqueue.c3 @@ -75,7 +75,7 @@ fn void LinkedBlockingQueue.free(&self) self.not_full.destroy(); } -fn void LinkedBlockingQueue.link_entry(&self, QueueEntry* entry) @private +fn void linkedblockingqueue_link_entry(LinkedBlockingQueue* self, QueueEntry* entry) @private { entry.next = null; entry.prev = self.tail; @@ -95,7 +95,7 @@ fn void LinkedBlockingQueue.link_entry(&self, QueueEntry* entry) @private } -fn QueueEntry* LinkedBlockingQueue.unlink_head(&self) @private +fn QueueEntry* linkedblockingqueue_unlink_head(LinkedBlockingQueue* self) @private { if (self.head == null) return null; @@ -134,7 +134,7 @@ fn void LinkedBlockingQueue.push(&self, Value value) .next = null, .prev = null }); - self.link_entry(entry); + linkedblockingqueue_link_entry(self, entry); // Signal that queue is no longer empty self.not_empty.signal(); @@ -156,7 +156,7 @@ fn Value LinkedBlockingQueue.poll(&self) self.not_empty.wait(&self.lock); } - QueueEntry* entry = self.unlink_head(); + QueueEntry* entry = linkedblockingqueue_unlink_head(self); Value value = entry.value; allocator::free(self.allocator, entry); if (self.capacity > 0) @@ -180,7 +180,7 @@ fn Value? LinkedBlockingQueue.pop(&self) { if (self.count == 0) return NO_MORE_ELEMENT~; - QueueEntry* entry = self.unlink_head(); + QueueEntry* entry = linkedblockingqueue_unlink_head(self); Value value = entry.value; allocator::free(self.allocator, entry); @@ -217,7 +217,7 @@ fn Value? LinkedBlockingQueue.poll_timeout(&self, Duration timeout) if (!self.count) return NO_MORE_ELEMENT~; } - QueueEntry* entry = self.unlink_head(); + QueueEntry* entry = linkedblockingqueue_unlink_head(self); Value value = entry.value; allocator::free(self.allocator, entry); @@ -273,7 +273,7 @@ fn void? LinkedBlockingQueue.try_push(&self, Value value) .next = null, .prev = null }); - self.link_entry(entry); + linkedblockingqueue_link_entry(self, entry); self.not_empty.signal(); }; } @@ -307,7 +307,7 @@ fn void? LinkedBlockingQueue.push_timeout(&self, Value value, Duration timeout) .next = null, .prev = null }); - self.link_entry(entry); + linkedblockingqueue_link_entry(self, entry); self.not_empty.signal(); }; } diff --git a/lib/std/collections/linked_hashmap.c3 b/lib/std/collections/linked_hashmap.c3 index ffe337595..3540ffddc 100644 --- a/lib/std/collections/linked_hashmap.c3 +++ b/lib/std/collections/linked_hashmap.c3 @@ -150,7 +150,7 @@ fn bool LinkedHashMap.is_initialized(&map) fn LinkedHashMap* LinkedHashMap.init_from_map(&self, Allocator allocator, LinkedHashMap* other_map) { self.init(allocator, other_map.table.len, other_map.load_factor); - self.put_all_for_create(other_map); + linkedhashmap_put_all_for_create(self, other_map); return self; } @@ -242,13 +242,13 @@ fn bool LinkedHashMap.set(&map, Key key, Value value) @operator([]=) return true; } } - map.add_entry(hash, key, value, index); + linkedhashmap_add_entry(map, hash, key, value, index); return false; } fn void? LinkedHashMap.remove(&map, Key key) @maydiscard { - if (!map.remove_entry_for_key(key)) return NOT_FOUND~; + if (!linkedhashmap_remove_entry_for_key(map, key)) return NOT_FOUND~; } fn void LinkedHashMap.clear(&map) @@ -259,7 +259,7 @@ fn void LinkedHashMap.clear(&map) while (entry) { LinkedEntry* next = entry.after; - map.free_entry(entry); + linkedhashmap_free_entry(map, entry); entry = next; } @@ -277,7 +277,7 @@ fn void LinkedHashMap.free(&map) { if (!map.is_initialized()) return; map.clear(); - map.free_internal(map.table.ptr); + linkedhashmap_free_internal(map, map.table.ptr); map.table = {}; } @@ -396,7 +396,7 @@ fn bool LinkedHashMapIterator.has_next(&self) // --- private methods -fn void LinkedHashMap.add_entry(&map, uint hash, Key key, Value value, uint bucket_index) @private +fn void linkedhashmap_add_entry(LinkedHashMap* map, uint hash, Key key, Value value, uint bucket_index) @private { $if COPY_KEYS: key = key.copy(map.allocator); @@ -428,11 +428,11 @@ fn void LinkedHashMap.add_entry(&map, uint hash, Key key, Value value, uint buck if (map.count++ >= map.threshold) { - map.resize(map.table.len * 2); + linkedhashmap_resize(map, map.table.len * 2); } } -fn void LinkedHashMap.resize(&map, uint new_capacity) @private +fn void linkedhashmap_resize(LinkedHashMap* map, uint new_capacity) @private { LinkedEntry*[] old_table = map.table; uint old_capacity = old_table.len; @@ -502,7 +502,7 @@ fn void LinkedHashMap.resize(&map, uint new_capacity) @private } } - map.free_internal(old_table.ptr); + linkedhashmap_free_internal(map, old_table.ptr); } fn usz? LinkedHashMap.to_format(&self, Formatter* f) @dynamic @@ -517,7 +517,7 @@ fn usz? LinkedHashMap.to_format(&self, Formatter* f) @dynamic return len + f.print(" }"); } -fn void LinkedHashMap.transfer(&map, LinkedEntry*[] new_table) @private +fn void linkedhashmap_transfer(LinkedHashMap* map, LinkedEntry*[] new_table) @private { LinkedEntry*[] src = map.table; uint new_capacity = new_table.len; @@ -536,7 +536,7 @@ fn void LinkedHashMap.transfer(&map, LinkedEntry*[] new_table) @private } } -fn void LinkedHashMap.put_all_for_create(&map, LinkedHashMap* other_map) @private +fn void linkedhashmap_put_all_for_create(LinkedHashMap* map, LinkedHashMap* other_map) @private { if (!other_map.count) return; other_map.@each(; Key key, Value value) { @@ -544,7 +544,7 @@ fn void LinkedHashMap.put_all_for_create(&map, LinkedHashMap* other_map) @privat }; } -fn void LinkedHashMap.put_for_create(&map, Key key, Value value) @private +fn void linkedhashmap_put_for_create(LinkedHashMap* map, Key key, Value value) @private { uint hash = rehash(key.hash()); uint i = index_for(hash, map.table.len); @@ -556,15 +556,15 @@ fn void LinkedHashMap.put_for_create(&map, Key key, Value value) @private return; } } - map.create_entry(hash, key, value, i); + linkedhashmap_create_entry(map, hash, key, value, i); } -fn void LinkedHashMap.free_internal(&map, void* ptr) @inline @private +fn void linkedhashmap_free_internal(LinkedHashMap* map, void* ptr) @inline @private { allocator::free(map.allocator, ptr); } -fn bool LinkedHashMap.remove_entry_for_key(&map, Key key) @private +fn bool linkedhashmap_remove_entry_for_key(LinkedHashMap* map, Key key) @private { if (!map.count) return false; @@ -605,7 +605,7 @@ fn bool LinkedHashMap.remove_entry_for_key(&map, Key key) @private } map.count--; - map.free_entry(e); + linkedhashmap_free_entry(map, e); return true; } prev = e; @@ -614,23 +614,23 @@ fn bool LinkedHashMap.remove_entry_for_key(&map, Key key) @private return false; } -fn void LinkedHashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_index) @private +fn void linkedhashmap_create_entry(LinkedHashMap* map, uint hash, Key key, Value value, int bucket_index) @private { LinkedEntry *e = map.table[bucket_index]; $if COPY_KEYS: - key = key.copy(map.allocator); + key = key.copy(map.allocator); $endif LinkedEntry* entry = allocator::new(map.allocator, LinkedEntry, { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] }); map.table[bucket_index] = entry; map.count++; } -fn void LinkedHashMap.free_entry(&self, LinkedEntry *entry) @local +fn void linkedhashmap_free_entry(LinkedHashMap* self, LinkedEntry *entry) @local { $if COPY_KEYS: - allocator::free(self.allocator, entry.key); + allocator::free(self.allocator, entry.key); $endif - self.free_internal(entry); + linkedhashmap_free_internal(self, entry); } diff --git a/lib/std/collections/linked_hashset.c3 b/lib/std/collections/linked_hashset.c3 index 9c80c3b11..77e89d4f7 100644 --- a/lib/std/collections/linked_hashset.c3 +++ b/lib/std/collections/linked_hashset.c3 @@ -143,7 +143,7 @@ fn LinkedHashSet* LinkedHashSet.init_from_set(&self, Allocator allocator, Linked LinkedEntry* entry = other_set.head; while (entry) // Save insertion order { - self.put_for_create(entry.value); + linkedhashset_put_for_create(self, entry.value); entry = entry.after; } return self; @@ -223,7 +223,7 @@ fn bool LinkedHashSet.add(&set, Value value) { if (e.hash == hash && equals(value, e.value)) return false; } - set.add_entry(hash, value, index); + linkedhashset_add_entry(set, hash, value, index); return true; } @@ -266,7 +266,7 @@ fn bool LinkedHashSet.contains(&set, Value value) *> fn void? LinkedHashSet.remove(&set, Value value) @maydiscard { - if (!set.remove_entry_for_value(value)) return NOT_FOUND~; + if (!linkedhashset_remove_entry_for_value(set, value)) return NOT_FOUND~; } fn usz LinkedHashSet.remove_all(&set, Value[] values) @@ -274,7 +274,7 @@ fn usz LinkedHashSet.remove_all(&set, Value[] values) usz total; foreach (v : values) { - if (set.remove_entry_for_value(v)) total++; + if (linkedhashset_remove_entry_for_value(set, v)) total++; } return total; } @@ -287,7 +287,7 @@ fn usz LinkedHashSet.remove_all_from(&set, LinkedHashSet* other) usz total; other.@each(;Value val) { - if (set.remove_entry_for_value(val)) total++; + if (linkedhashset_remove_entry_for_value(set, val)) total++; }; return total; } @@ -299,7 +299,7 @@ fn void LinkedHashSet.free(&set) { if (!set.is_initialized()) return; set.clear(); - set.free_internal(set.table.ptr); + linkedhashset_free_internal(set, set.table.ptr); set.table = {}; } @@ -316,7 +316,7 @@ fn void LinkedHashSet.clear(&set) while (entry) { LinkedEntry* next = entry.after; - set.free_entry(entry); + linkedhashset_free_entry(set, entry); entry = next; } @@ -334,7 +334,7 @@ fn void LinkedHashSet.reserve(&set, usz capacity) { if (capacity > set.threshold) { - set.resize(math::next_power_of_2(capacity)); + linkedhashset_resize(set, math::next_power_of_2(capacity)); } } @@ -451,7 +451,7 @@ fn bool LinkedHashSet.is_subset(&self, LinkedHashSet* other) // --- private methods -fn void LinkedHashSet.add_entry(&set, uint hash, Value value, uint bucket_index) @private +fn void linkedhashset_add_entry(LinkedHashSet* set, uint hash, Value value, uint bucket_index) @private { LinkedEntry* entry = allocator::new(set.allocator, LinkedEntry, { .hash = hash, @@ -478,11 +478,11 @@ fn void LinkedHashSet.add_entry(&set, uint hash, Value value, uint bucket_index) if (set.count++ >= set.threshold) { - set.resize(set.table.len * 2); + linkedhashset_resize(set, set.table.len * 2); } } -fn void LinkedHashSet.resize(&set, usz new_capacity) @private +fn void linkedhashset_resize(LinkedHashSet* set, usz new_capacity) @private { LinkedEntry*[] old_table = set.table; usz old_capacity = old_table.len; @@ -552,7 +552,7 @@ fn void LinkedHashSet.resize(&set, usz new_capacity) @private } } - set.free_internal(old_table.ptr); + linkedhashset_free_internal(set, old_table.ptr); } fn usz? LinkedHashSet.to_format(&self, Formatter* f) @dynamic @@ -567,7 +567,7 @@ fn usz? LinkedHashSet.to_format(&self, Formatter* f) @dynamic return len + f.print(" }"); } -fn void LinkedHashSet.transfer(&set, LinkedEntry*[] new_table) @private +fn void linked_hashset_transfer(LinkedHashSet* set, LinkedEntry*[] new_table) @private { LinkedEntry*[] src = set.table; uint new_capacity = new_table.len; @@ -586,7 +586,7 @@ fn void LinkedHashSet.transfer(&set, LinkedEntry*[] new_table) @private } } -fn void LinkedHashSet.put_for_create(&set, Value value) @private +fn void linkedhashset_put_for_create(LinkedHashSet* set, Value value) @private { uint hash = rehash(value.hash()); uint i = index_for(hash, set.table.len); @@ -598,15 +598,15 @@ fn void LinkedHashSet.put_for_create(&set, Value value) @private return; } } - set.create_entry(hash, value, i); + linkedhashset_create_entry(set, hash, value, i); } -fn void LinkedHashSet.free_internal(&set, void* ptr) @inline @private +fn void linkedhashset_free_internal(LinkedHashSet* set, void* ptr) @inline @private { allocator::free(set.allocator, ptr); } -fn void LinkedHashSet.create_entry(&set, uint hash, Value value, int bucket_index) @private +fn void linkedhashset_create_entry(LinkedHashSet* set, uint hash, Value value, int bucket_index) @private { LinkedEntry* entry = allocator::new(set.allocator, LinkedEntry, { .hash = hash, @@ -633,7 +633,7 @@ fn void LinkedHashSet.create_entry(&set, uint hash, Value value, int bucket_inde set.count++; } -fn bool LinkedHashSet.remove_entry_for_value(&set, Value value) @private +fn bool linkedhashset_remove_entry_for_value(LinkedHashSet* set, Value value) @private { if (!set.count) return false; @@ -674,7 +674,7 @@ fn bool LinkedHashSet.remove_entry_for_value(&set, Value value) @private } set.count--; - set.free_entry(e); + linkedhashset_free_entry(set, e); return true; } prev = e; @@ -683,7 +683,7 @@ fn bool LinkedHashSet.remove_entry_for_value(&set, Value value) @private return false; } -fn void LinkedHashSet.free_entry(&set, LinkedEntry *entry) @private +fn void linkedhashset_free_entry(LinkedHashSet* set, LinkedEntry *entry) @private { allocator::free(set.allocator, entry); } diff --git a/lib/std/collections/linkedlist.c3 b/lib/std/collections/linkedlist.c3 index 787aa39b3..58a320713 100644 --- a/lib/std/collections/linkedlist.c3 +++ b/lib/std/collections/linkedlist.c3 @@ -217,7 +217,7 @@ fn usz? LinkedList.rindex_of(&self, Type t) @if(ELEMENT_IS_EQUATABLE) *> fn void LinkedList.remove_at(&self, usz index) { - self.unlink(self.node_at_index(index)); + linked_list_unlink(self, self.node_at_index(index)); } <* @@ -232,47 +232,47 @@ fn void LinkedList.insert_at(&self, usz index, Type element) case self.size: self.push(element); default: - self.link_before(self.node_at_index(index), element); + linked_list_link_before(self, self.node_at_index(index), element); } } <* @require succ != null *> -fn void LinkedList.link_before(&self, Node *succ, Type value) @private +fn void linked_list_link_before(LinkedList* l, Node *succ, Type value) @private { Node* pred = succ.prev; - Node* new_node = self.alloc_node(); + Node* new_node = l.alloc_node(); *new_node = { .prev = pred, .next = succ, .value = value }; succ.prev = new_node; if (!pred) { - self._first = new_node; + l._first = new_node; } else { pred.next = new_node; } - self.size++; + l.size++; } <* - @require self._first != null + @require l._first != null *> -fn void LinkedList.unlink_first(&self) @private +fn void linked_list_unlink_first(LinkedList* l) @private { - Node* f = self._first; + Node* f = l._first; Node* next = f.next; - self.free_node(f); - self._first = next; + l.free_node(f); + l._first = next; if (!next) { - self._last = null; + l._last = null; } else { next.prev = null; } - self.size--; + l.size--; } fn usz LinkedList.remove(&self, Type t) @if(ELEMENT_IS_EQUATABLE) @@ -285,7 +285,7 @@ fn usz LinkedList.remove(&self, Type t) @if(ELEMENT_IS_EQUATABLE) { case equals(node.value, t): Node* next = node.next; - self.unlink(node); + linked_list_unlink(self, node); node = next; default: node = node.next; @@ -297,7 +297,7 @@ fn usz LinkedList.remove(&self, Type t) @if(ELEMENT_IS_EQUATABLE) fn Type? LinkedList.pop(&self) { if (!self._last) return NO_MORE_ELEMENT~; - defer self.unlink_last(); + defer linked_list_unlink_last(self); return self._last.value; } @@ -309,20 +309,20 @@ fn bool LinkedList.is_empty(&self) fn Type? LinkedList.pop_front(&self) { if (!self._first) return NO_MORE_ELEMENT~; - defer self.unlink_first(); + defer linked_list_unlink_first(self); return self._first.value; } fn void? LinkedList.remove_last(&self) @maydiscard { if (!self._first) return NO_MORE_ELEMENT~; - self.unlink_last(); + linked_list_unlink_last(self); } fn void? LinkedList.remove_first(&self) @maydiscard { if (!self._first) return NO_MORE_ELEMENT~; - self.unlink_first(); + linked_list_unlink_first(self); } @@ -332,7 +332,7 @@ fn bool LinkedList.remove_first_match(&self, Type t) @if(ELEMENT_IS_EQUATABLE) { if (node.value == t) { - self.unlink(node); + linked_list_unlink(self, node); return true; } } @@ -345,7 +345,7 @@ fn bool LinkedList.remove_last_match(&self, Type t) @if(ELEMENT_IS_EQUATABLE) { if (node.value == t) { - self.unlink(node); + linked_list_unlink(self, node); return true; } } @@ -354,7 +354,7 @@ fn bool LinkedList.remove_last_match(&self, Type t) @if(ELEMENT_IS_EQUATABLE) <* @require self._last != null *> -fn void LinkedList.unlink_last(&self) @inline @private +fn void linked_list_unlink_last(LinkedList* self) @inline @private { Node* l = self._last; Node* prev = l.prev; @@ -374,7 +374,7 @@ fn void LinkedList.unlink_last(&self) @inline @private <* @require x != null *> -fn void LinkedList.unlink(&self, Node* x) @private +fn void linked_list_unlink(LinkedList* self, 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 274a739aa..8a9a7c9e0 100644 --- a/lib/std/collections/list.c3 +++ b/lib/std/collections/list.c3 @@ -82,7 +82,7 @@ fn void List.init_wrapping_array(&self, Allocator allocator, Type[] types) self.allocator = allocator; self.capacity = types.len; self.entries = types.ptr; - self.set_size(types.len); + list_set_size(self, types.len); } fn bool List.is_initialized(&self) @inline => self.allocator != null && self.allocator != (Allocator)&dummy; @@ -110,19 +110,19 @@ fn usz? List.to_format(&self, Formatter* formatter) @dynamic fn void List.push(&self, Type element) @inline { self.reserve(1); - self.entries[self.set_size(self.size + 1)] = element; + self.entries[list_set_size(self, self.size + 1)] = element; } fn Type? List.pop(&self) { if (!self.size) return NO_MORE_ELEMENT~; - defer self.set_size(self.size - 1); + defer list_set_size(self, self.size - 1); return self.entries[self.size - 1]; } fn void List.clear(&self) { - self.set_size(0); + list_set_size(self, 0); } fn Type? List.pop_first(&self) @@ -138,7 +138,7 @@ fn Type? List.pop_first(&self) fn void List.remove_at(&self, usz index) { usz new_size = self.size - 1; - defer self.set_size(new_size); + defer list_set_size(self, new_size); if (!new_size || index == new_size) return; self.entries[index .. new_size - 1] = self.entries[index + 1 .. new_size]; } @@ -147,7 +147,7 @@ fn void List.add_all(&self, List* other_list) { if (!other_list.size) return; self.reserve(other_list.size); - usz index = self.set_size(self.size + other_list.size); + usz index = list_set_size(self, self.size + other_list.size); foreach (&value : other_list) { self.entries[index++] = *value; @@ -203,7 +203,7 @@ fn void List.add_array(&self, Type[] array) @deprecated("Use push_all") { if (!array.len) return; self.reserve(array.len); - usz index = self.set_size(self.size + array.len); + usz index = list_set_size(self, self.size + array.len); self.entries[index : array.len] = array[..]; } @@ -217,7 +217,7 @@ fn void List.push_all(&self, Type[] array) { if (!array.len) return; self.reserve(array.len); - usz index = self.set_size(self.size + array.len); + usz index = list_set_size(self, self.size + array.len); self.entries[index : array.len] = array[..]; } @@ -232,7 +232,7 @@ fn void List.push_front(&self, Type type) @inline fn void List.insert_at(&self, usz index, Type type) { self.reserve(1); - self.set_size(self.size + 1); + list_set_size(self, self.size + 1); for (isz i = self.size - 1; i > index; i--) { self.entries[i] = self.entries[i - 1]; @@ -251,7 +251,7 @@ fn void List.set_at(&self, usz index, Type type) fn void? List.remove_last(&self) @maydiscard { if (!self.size) return NO_MORE_ELEMENT~; - self.set_size(self.size - 1); + list_set_size(self, self.size - 1); } fn void? List.remove_first(&self) @maydiscard @@ -299,7 +299,7 @@ fn void List.free(&self) { if (!self.allocator || self.allocator.ptr == &dummy || !self.capacity) return; - self.pre_free(); // Remove sanitizer annotation + list_pre_free(self); // Remove sanitizer annotation $if type_is_overaligned(): allocator::free_aligned(self.allocator, self.entries); @@ -358,7 +358,7 @@ fn usz List.retain_using_test(&self, ElementTest filter, any context) return list_common::list_remove_using_test(self, filter, true, context); } -fn void List.ensure_capacity(&self, usz min_capacity) @local +fn void list_ensure_capacity(List* self, usz min_capacity) @local { if (!min_capacity) return; if (self.capacity >= min_capacity) return; @@ -374,7 +374,7 @@ fn void List.ensure_capacity(&self, usz min_capacity) @local break; } - self.pre_free(); // Remove sanitizer annotation + list_pre_free(self); // Remove sanitizer annotation min_capacity = math::next_power_of_2(min_capacity); $if type_is_overaligned(): @@ -384,7 +384,7 @@ fn void List.ensure_capacity(&self, usz min_capacity) @local $endif; self.capacity = min_capacity; - self.post_alloc(); // Add sanitizer annotation + list_post_alloc(self); // Add sanitizer annotation } <* @@ -419,7 +419,7 @@ fn void List.reserve(&self, usz added) assert(new_size < usz.max / 2U); usz new_capacity = self.capacity ? 2U * self.capacity : 16U; while (new_capacity < new_size) new_capacity *= 2U; - self.ensure_capacity(new_capacity); + list_ensure_capacity(self, new_capacity); } fn void List._update_size_change(&self,usz old_size, usz new_size) @@ -436,7 +436,7 @@ fn void List._update_size_change(&self,usz old_size, usz new_size) <* @require new_size == 0 || self.capacity != 0 *> -fn usz List.set_size(&self, usz new_size) @inline @private +fn usz list_set_size(List* self, usz new_size) @inline @private { usz old_size = self.size; self._update_size_change(old_size, new_size); @@ -444,7 +444,7 @@ fn usz List.set_size(&self, usz new_size) @inline @private return old_size; } -macro void List.pre_free(&self) @private +macro void list_pre_free(List* self) @private { if (!self.capacity) return; self._update_size_change(self.size, self.capacity); @@ -453,7 +453,7 @@ macro void List.pre_free(&self) @private <* @require self.capacity > 0 *> -macro void List.post_alloc(&self) @private +macro void list_post_alloc(List* self) @private { self._update_size_change(self.capacity, self.size); } diff --git a/lib/std/collections/object.c3 b/lib/std/collections/object.c3 index 780e2fff3..45dae5a7f 100644 --- a/lib/std/collections/object.c3 +++ b/lib/std/collections/object.c3 @@ -151,7 +151,7 @@ fn bool Object.is_indexable(&self) => self.is_empty() || self.is_array(); <* @require self.is_keyable() *> -fn void Object.init_map_if_needed(&self) @private +fn void object_init_map_if_needed(Object* self) @private { if (self.is_empty()) { @@ -163,7 +163,7 @@ fn void Object.init_map_if_needed(&self) @private <* @require self.is_indexable() *> -fn void Object.init_array_if_needed(&self) @private +fn void object_init_array_if_needed(Object* self) @private { if (self.is_empty()) { @@ -175,9 +175,9 @@ fn void Object.init_array_if_needed(&self) @private <* @require self.is_keyable() *> -fn void Object.set_object(&self, String key, Object* new_object) @private +fn void object_set_object(Object* self, String key, Object* new_object) @private { - self.init_map_if_needed(); + object_init_map_if_needed(self); Object*? val = self.map.get_entry(key).value; defer (void)val.free(); self.map.set(key, new_object); @@ -214,7 +214,7 @@ macro Object* Object.object_from_value(&self, value) @private macro Object* Object.set(&self, String key, value) { Object* val = self.object_from_value(value); - self.set_object(key, val); + object_set_object(self, key, val); return val; } @@ -267,7 +267,7 @@ fn usz Object.get_len(&self) *> fn void Object.push_object(&self, Object* to_append) { - self.init_array_if_needed(); + object_init_array_if_needed(self); self.array.push(to_append); } @@ -276,7 +276,7 @@ fn void Object.push_object(&self, Object* to_append) *> fn void Object.set_object_at(&self, usz index, Object* to_set) { - self.init_array_if_needed(); + object_init_array_if_needed(self); while (self.array.len() < index) { self.array.push(&NULL_OBJECT); diff --git a/lib/std/compression/deflate.c3 b/lib/std/compression/deflate.c3 index 3a805ea01..31783c2c3 100644 --- a/lib/std/compression/deflate.c3 +++ b/lib/std/compression/deflate.c3 @@ -90,7 +90,7 @@ fn usz? Inflater.read(&self, char[] buffer) @dynamic if (self.pos - self.read_pos >= 32768U) break; - self.step()!; + inflater_step(self)!; } return total_out; @@ -521,7 +521,7 @@ fn void StreamBitReader.close(&self) } } -fn void? StreamBitReader.refill(&self) @private @inline +fn void? StreamBitReader.refill(&self) @inline { if (self.buf_pos >= self.buf_len) { @@ -532,7 +532,7 @@ fn void? StreamBitReader.refill(&self) @private @inline } } -fn uint? StreamBitReader.read_bits(&self, uint count) @private @inline +fn uint? StreamBitReader.read_bits(&self, uint count) @inline { if (count == 0) return 0; if (self.nbits < count) @@ -554,7 +554,7 @@ fn uint? StreamBitReader.read_bits(&self, uint count) @private @inline return value; } -fn void StreamBitReader.align(&self) @private @inline +fn void StreamBitReader.align(&self) @inline { uint skip = self.nbits % 8; self.bit_buf >>= skip; @@ -570,7 +570,7 @@ struct BitWriter @private Allocator allocator; } -fn void BitWriter.init(&self, Allocator allocator, usz initial_cap) @private +fn void BitWriter.init(&self, Allocator allocator, usz initial_cap) { self.allocator = allocator; self.data = allocator::alloc_array(allocator, char, initial_cap); @@ -579,7 +579,7 @@ fn void BitWriter.init(&self, Allocator allocator, usz initial_cap) @private self.nbits = 0; } -fn void BitWriter.write_bits(&self, uint value, uint count) @private +fn void BitWriter.write_bits(&self, uint value, uint count) { self.buffer |= (ulong)(value & ((1 << count) - 1)) << self.nbits; self.nbits += count; @@ -602,13 +602,13 @@ fn void BitWriter.write_bits(&self, uint value, uint count) @private } } -fn void BitWriter.write_huffman(&self, uint code, uint len) @private +fn void BitWriter.write_huffman(&self, uint code, uint len) { uint rev = bits::reverse(code << (32 - len)); self.write_bits(rev, len); } -fn char[] BitWriter.finish(&self) @private +fn char[] BitWriter.finish(&self) { if (self.nbits > 0) { @@ -630,7 +630,7 @@ struct Huffman @private ushort[288] symbols; } -fn void Huffman.build(&self, char[] lengths) @private +fn void Huffman.build(&self, char[] lengths) { ushort[16] offsets; self.counts = {}; @@ -805,7 +805,7 @@ fn char[] pkg_merge(Allocator allocator, uint[] freqs, uint max_bits) @private = return blen; } -fn char[] Huffman.get_lengths(&self, usz max_sym) @private +fn char[] Huffman.get_lengths(&self, usz max_sym) { char[] blen = allocator::new_array(tmem, char, max_sym + 1); @@ -821,7 +821,7 @@ fn char[] Huffman.get_lengths(&self, usz max_sym) @private return blen; } -fn void Huffman.build_from_freqs(&self, uint[] freqs, uint max_bits) @private => @pool() +fn void Huffman.build_from_freqs(&self, uint[] freqs, uint max_bits) => @pool() { char[] blen = pkg_merge(tmem, freqs, max_bits); self.build(blen); @@ -922,7 +922,7 @@ fn void gen_fixed_codes(Code* codes) @private } } -fn ushort? Huffman.decode_stream(&self, StreamBitReader* reader) @private @inline +fn ushort? Huffman.decode_stream(&self, StreamBitReader* reader) @inline { uint code = 0; uint first = 0; @@ -943,7 +943,7 @@ fn ushort? Huffman.decode_stream(&self, StreamBitReader* reader) @private @inlin return CORRUPTED_DATA~; } -fn void? Inflater.step(&self) @private +fn void? inflater_step(Inflater* self) @private { switch (self.state) { @@ -975,7 +975,7 @@ fn void? Inflater.step(&self) @private self.state = COPY_STORED; case COPY_STORED: char c = (char)self.reader.read_bits(8)!; - self.write_byte(c); + inflater_write_byte(self, c); self.stored_len--; if (self.stored_len == 0) { @@ -1045,7 +1045,7 @@ fn void? Inflater.step(&self) @private switch { case symbol < 256: - self.write_byte((char)symbol); + inflater_write_byte(self, (char)symbol); case symbol == 256: self.state = self.final ? DONE : START_BLOCK; case symbol <= 285: @@ -1064,7 +1064,7 @@ fn void? Inflater.step(&self) @private case COPY_MATCH: if (self.match_dist > self.pos) return CORRUPTED_DATA~; char c = self.window[(usz)((self.pos - self.match_dist) & 0xFFFF)]; - self.write_byte(c); + inflater_write_byte(self, c); self.match_len--; if (self.match_len == 0) { @@ -1078,7 +1078,7 @@ fn void? Inflater.step(&self) @private return; } -fn void Inflater.write_byte(&self, char c) @private @inline +fn void inflater_write_byte(Inflater* self, char c) @private @inline { self.window[(usz)(self.pos & 0xFFFF)] = c; self.pos++; diff --git a/lib/std/core/allocators/backed_arena_allocator.c3 b/lib/std/core/allocators/backed_arena_allocator.c3 index 6419582a3..57f710033 100644 --- a/lib/std/core/allocators/backed_arena_allocator.c3 +++ b/lib/std/core/allocators/backed_arena_allocator.c3 @@ -56,7 +56,7 @@ fn BackedArenaAllocator*? new_backed_allocator(usz size, Allocator allocator) fn void BackedArenaAllocator.destroy(&self) { self.reset(0); - if (self.last_page) (void)self._free_page(self.last_page); + if (self.last_page) (void)_free_page(self, self.last_page); allocator::free(self.backing_allocator, self); } @@ -79,7 +79,7 @@ fn void BackedArenaAllocator.reset(&self, usz mark) self.used = last_page.mark; ExtraPage *to_free = last_page; last_page = last_page.prev_page; - self._free_page(to_free)!!; + _free_page(self, to_free)!!; } self.last_page = last_page; $if env::COMPILER_SAFE_MODE || env::ADDRESS_SANITIZER: @@ -98,13 +98,13 @@ fn void BackedArenaAllocator.reset(&self, usz mark) self.used = mark; } -fn void? BackedArenaAllocator._free_page(&self, ExtraPage* page) @inline @local +fn void? _free_page(BackedArenaAllocator* self, ExtraPage* page) @inline @local { void* mem = page.start; return self.backing_allocator.release(mem, page.is_aligned()); } -fn void*? BackedArenaAllocator._realloc_page(&self, ExtraPage* page, usz size, usz alignment) @inline @local +fn void*? _realloc_page(BackedArenaAllocator* self, ExtraPage* page, usz size, usz alignment) @inline @local { // Then the actual start pointer: void* real_pointer = page.start; @@ -133,7 +133,7 @@ fn void*? BackedArenaAllocator.resize(&self, void* pointer, usz size, usz alignm assert(self.last_page, "Realloc of unrelated pointer"); // First grab the page ExtraPage *page = pointer - ExtraPage.sizeof; - return self._realloc_page(page, size, alignment); + return _realloc_page(self, page, size, alignment); } AllocChunk* data = self.acquire(size, NO_ZERO, alignment)!; diff --git a/lib/std/core/allocators/dynamic_arena.c3 b/lib/std/core/allocators/dynamic_arena.c3 index c5273bbdb..a25ee2726 100644 --- a/lib/std/core/allocators/dynamic_arena.c3 +++ b/lib/std/core/allocators/dynamic_arena.c3 @@ -137,12 +137,67 @@ fn void DynamicArenaAllocator.reset(&self) self.page = page; } + + +<* + @require size > 0 : `acquire expects size > 0` + @require !alignment || math::is_power_of_2(alignment) + @return? mem::INVALID_ALLOC_SIZE, mem::OUT_OF_MEMORY +*> +fn void*? DynamicArenaAllocator.acquire(&self, usz size, AllocInitType init_type, usz alignment) @dynamic +{ + alignment = alignment_for_allocation(alignment); + DynamicArenaPage* page = self.page; + + void* ptr @noinit; + do SET_DONE: + { + if (!page && self.unused_page) + { + self.page = page = self.unused_page; + self.unused_page = page.prev_arena; + page.prev_arena = null; + } + if (!page) + { + ptr = _alloc_new(self, size, alignment)!; + break SET_DONE; + } + void* start = mem::aligned_pointer(page.memory + page.used + DynamicArenaChunk.sizeof, alignment); + usz new_used = start - page.memory + size; + if ALLOCATE_NEW: (new_used > page.total) + { + if ((page = self.unused_page)) + { + start = mem::aligned_pointer(page.memory + page.used + DynamicArenaChunk.sizeof, alignment); + new_used = start + size - page.memory; + if (page.total >= new_used) + { + self.unused_page = page.prev_arena; + page.prev_arena = self.page; + self.page = page; + break ALLOCATE_NEW; + } + } + ptr = _alloc_new(self, size, alignment)!; + break SET_DONE; + } + page.used = new_used; + assert(start + size == page.memory + page.used); + ptr = start; + DynamicArenaChunk* chunk = (DynamicArenaChunk*)ptr - 1; + chunk.size = size; + }; + if (init_type == ZERO) mem::clear(ptr, size, mem::DEFAULT_MEM_ALIGNMENT); + return ptr; +} + <* @require math::is_power_of_2(alignment) @require size > 0 @return? mem::INVALID_ALLOC_SIZE, mem::OUT_OF_MEMORY *> -fn void*? DynamicArenaAllocator._alloc_new(&self, usz size, usz alignment) @local +fn void*? _alloc_new(DynamicArenaAllocator* self, usz size, usz alignment) @local { // First, make sure that we can align it, extending the page size if needed. usz page_size = max(self.page_size, mem::aligned_offset(size + DynamicArenaChunk.sizeof + alignment, alignment)); @@ -166,57 +221,4 @@ fn void*? DynamicArenaAllocator._alloc_new(&self, usz size, usz alignment) @loca self.page = page; page.current_stack_ptr = mem_start; return mem_start; -} - -<* - @require size > 0 : `acquire expects size > 0` - @require !alignment || math::is_power_of_2(alignment) - @return? mem::INVALID_ALLOC_SIZE, mem::OUT_OF_MEMORY -*> -fn void*? DynamicArenaAllocator.acquire(&self, usz size, AllocInitType init_type, usz alignment) @dynamic -{ - alignment = alignment_for_allocation(alignment); - DynamicArenaPage* page = self.page; - - void* ptr @noinit; - do SET_DONE: - { - if (!page && self.unused_page) - { - self.page = page = self.unused_page; - self.unused_page = page.prev_arena; - page.prev_arena = null; - } - if (!page) - { - ptr = self._alloc_new(size, alignment)!; - break SET_DONE; - } - void* start = mem::aligned_pointer(page.memory + page.used + DynamicArenaChunk.sizeof, alignment); - usz new_used = start - page.memory + size; - if ALLOCATE_NEW: (new_used > page.total) - { - if ((page = self.unused_page)) - { - start = mem::aligned_pointer(page.memory + page.used + DynamicArenaChunk.sizeof, alignment); - new_used = start + size - page.memory; - if (page.total >= new_used) - { - self.unused_page = page.prev_arena; - page.prev_arena = self.page; - self.page = page; - break ALLOCATE_NEW; - } - } - ptr = self._alloc_new(size, alignment)!; - break SET_DONE; - } - page.used = new_used; - assert(start + size == page.memory + page.used); - ptr = start; - DynamicArenaChunk* chunk = (DynamicArenaChunk*)ptr - 1; - chunk.size = size; - }; - if (init_type == ZERO) mem::clear(ptr, size, mem::DEFAULT_MEM_ALIGNMENT); - return ptr; -} +} \ No newline at end of file diff --git a/lib/std/core/allocators/heap_allocator.c3 b/lib/std/core/allocators/heap_allocator.c3 index 61b3f8a60..aa91b9b11 100644 --- a/lib/std/core/allocators/heap_allocator.c3 +++ b/lib/std/core/allocators/heap_allocator.c3 @@ -32,58 +32,58 @@ fn void*? SimpleHeapAllocator.acquire(&self, usz size, AllocInitType init_type, { if (init_type == ZERO) { - return alignment > 0 ? @aligned_alloc(self._calloc, size, alignment) : self._calloc(size); + return alignment > 0 ? @aligned_alloc_fn(self, simple_alloc_calloc, size, alignment) : simple_alloc_calloc(self, size); } - return alignment > 0 ? @aligned_alloc(self._alloc, size, alignment) : self._alloc(size); + return alignment > 0 ? @aligned_alloc_fn(self, simple_alloc_alloc, size, alignment) : simple_alloc_alloc(self, size); } fn void*? SimpleHeapAllocator.resize(&self, void* old_pointer, usz size, usz alignment) @dynamic { return alignment > 0 - ? @aligned_realloc(self._calloc, self._free, old_pointer, size, alignment) - : self._realloc(old_pointer, size); + ? @aligned_realloc_fn(self, simple_alloc_calloc, simple_alloc_free, old_pointer, size, alignment) + : simple_alloc_realloc(self, old_pointer, size); } fn void SimpleHeapAllocator.release(&self, void* old_pointer, bool aligned) @dynamic { if (aligned) { - @aligned_free(self._free, old_pointer)!!; + @aligned_free_fn(self, simple_alloc_free, old_pointer)!!; } else { - self._free(old_pointer); + simple_alloc_free(self, old_pointer); } } <* @require old_pointer && bytes > 0 *> -fn void*? SimpleHeapAllocator._realloc(&self, void* old_pointer, usz bytes) @local +fn void*? simple_alloc_realloc(SimpleHeapAllocator* self, void* old_pointer, usz bytes) @local { // Find the block header. Header* block = (Header*)old_pointer - 1; if (block.size >= bytes) return old_pointer; - void* new = self._alloc(bytes)!; + void* new = simple_alloc_alloc(self, bytes)!; usz max_to_copy = math::min(block.size, bytes); mem::copy(new, old_pointer, max_to_copy); - self._free(old_pointer); + simple_alloc_free(self, old_pointer); return new; } -fn void*? SimpleHeapAllocator._calloc(&self, usz bytes) @local +fn void*? simple_alloc_calloc(SimpleHeapAllocator* self, usz bytes) @local { - void* data = self._alloc(bytes)!; + void* data = simple_alloc_alloc(self, bytes)!; mem::clear(data, bytes, mem::DEFAULT_MEM_ALIGNMENT); return data; } -fn void*? SimpleHeapAllocator._alloc(&self, usz bytes) @local +fn void*? simple_alloc_alloc(SimpleHeapAllocator* self, usz bytes) @local { usz aligned_bytes = mem::aligned_offset(bytes, mem::DEFAULT_MEM_ALIGNMENT); if (!self.free_list) { - self.add_block(aligned_bytes)!; + simple_alloc_add_block(self, aligned_bytes)!; } Header* current = self.free_list; @@ -123,22 +123,22 @@ fn void*? SimpleHeapAllocator._alloc(&self, usz bytes) @local current = current.next; } } - self.add_block(aligned_bytes)!; - return self._alloc(aligned_bytes); + simple_alloc_add_block(self, aligned_bytes)!; + return simple_alloc_alloc(self, aligned_bytes); } -fn void? SimpleHeapAllocator.add_block(&self, usz aligned_bytes) @local +fn void? simple_alloc_add_block(SimpleHeapAllocator* self, usz aligned_bytes) @local { assert(mem::aligned_offset(aligned_bytes, mem::DEFAULT_MEM_ALIGNMENT) == aligned_bytes); char[] result = self.alloc_fn(aligned_bytes + Header.sizeof)!; Header* new_block = (Header*)result.ptr; new_block.size = result.len - Header.sizeof; new_block.next = null; - self._free(new_block + 1); + simple_alloc_free(self, new_block + 1); } -fn void SimpleHeapAllocator._free(&self, void* ptr) @local +fn void simple_alloc_free(SimpleHeapAllocator* self, void* ptr) @local { // Empty ptr -> do nothing. if (!ptr) return; diff --git a/lib/std/core/allocators/temp_allocator.c3 b/lib/std/core/allocators/temp_allocator.c3 index d63150584..099ad700d 100644 --- a/lib/std/core/allocators/temp_allocator.c3 +++ b/lib/std/core/allocators/temp_allocator.c3 @@ -127,7 +127,7 @@ fn void TempAllocator.reset(&self) { TempAllocator* old = child; child = old.derived; - old.destroy(); + temp_allocator_destroy(old); } self.capacity = self.original_capacity; $if env::ADDRESS_SANITIZER: @@ -142,17 +142,17 @@ fn void TempAllocator.reset(&self) fn void TempAllocator.free(&self) { self.reset(); - self.destroy(); + temp_allocator_destroy(self); } -fn void TempAllocator.destroy(&self) @local +fn void temp_allocator_destroy(TempAllocator* self) { TempAllocatorPage *last_page = self.last_page; while (last_page) { TempAllocatorPage *to_free = last_page; last_page = last_page.prev_page; - self._free_page(to_free)!!; + _free_page(self, to_free)!!; } if (self.allocated) { @@ -179,33 +179,6 @@ fn void TempAllocator.release(&self, void* old_pointer, bool) @dynamic } -fn void? TempAllocator._free_page(&self, TempAllocatorPage* page) @inline @local -{ - void* mem = page.start; - return self.backing_allocator.release(mem, page.is_aligned()); -} - -fn void*? TempAllocator._realloc_page(&self, TempAllocatorPage* page, usz size, usz alignment) @inline @local -{ - // Then the actual start pointer: - void* real_pointer = page.start; - - // Walk backwards to find the pointer to this page. - TempAllocatorPage **pointer_to_prev = &self.last_page; - // Remove the page from the list - while (*pointer_to_prev != page) - { - pointer_to_prev = &((*pointer_to_prev).prev_page); - } - *pointer_to_prev = page.prev_page; - usz page_size = page.pagesize(); - // Clear on size > original size. - void* data = self.acquire(size, NO_ZERO, alignment)!; - if (page_size > size) page_size = size; - mem::copy(data, &page.data[0], page_size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT); - self.backing_allocator.release(real_pointer, page.is_aligned()); - return data; -} fn void*? TempAllocator.resize(&self, void* pointer, usz size, usz alignment) @dynamic { @@ -215,7 +188,7 @@ fn void*? TempAllocator.resize(&self, void* pointer, usz size, usz alignment) @d assert(self.last_page, "Realloc of non temp pointer"); // First grab the page TempAllocatorPage *page = pointer - TempAllocatorPage.sizeof; - return self._realloc_page(page, size, alignment); + return _realloc_page(self, page, size, alignment); } bool is_realloc_of_last = chunk.size + pointer == &self.data[self.used]; if (is_realloc_of_last) @@ -326,9 +299,39 @@ fn void*? TempAllocator.acquire(&self, usz size, AllocInitType init_type, usz al return &page.data[0]; } + +fn void? _free_page(TempAllocator* self, TempAllocatorPage* page) @inline @local +{ + void* mem = page.start; + return self.backing_allocator.release(mem, page.is_aligned()); +} + +fn void*? _realloc_page(TempAllocator* self, TempAllocatorPage* page, usz size, usz alignment) @inline @local +{ + // Then the actual start pointer: + void* real_pointer = page.start; + + // Walk backwards to find the pointer to this page. + TempAllocatorPage **pointer_to_prev = &self.last_page; + // Remove the page from the list + while (*pointer_to_prev != page) + { + pointer_to_prev = &((*pointer_to_prev).prev_page); + } + *pointer_to_prev = page.prev_page; + usz page_size = page.pagesize(); + // Clear on size > original size. + void* data = self.acquire(size, NO_ZERO, alignment)!; + if (page_size > size) page_size = size; + mem::copy(data, &page.data[0], page_size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT); + self.backing_allocator.release(real_pointer, page.is_aligned()); + return data; +} + module std::core::mem::allocator @if((env::POSIX || env::WIN32) && $feature(VMEM_TEMP)); import std::math; + tlocal VmemOptions temp_allocator_default_options = { .shrink_on_reset = env::MEMORY_ENV != NORMAL, .protect_unused_pages = env::COMPILER_OPT_LEVEL <= O1 || env::COMPILER_SAFE_MODE, @@ -383,10 +386,10 @@ fn void TempAllocator.reset(&self) } fn void TempAllocator.free(&self) { - self.destroy(); + _destroy(self); } -fn void TempAllocator.destroy(&self) @local +fn void _destroy(TempAllocator* self) @local { TempAllocator* child = self.derived; if (!child) return; @@ -403,4 +406,4 @@ fn void*? TempAllocator.resize(&self, void* pointer, usz size, usz alignment) @d fn void TempAllocator.release(&self, void* old_pointer, bool b) @dynamic { self.vmem.release(old_pointer, b) @inline; -} \ No newline at end of file +} diff --git a/lib/std/core/dstring.c3 b/lib/std/core/dstring.c3 index 59dd5aa2c..468c43075 100644 --- a/lib/std/core/dstring.c3 +++ b/lib/std/core/dstring.c3 @@ -631,7 +631,7 @@ fn void DString.reverse(self) } } -fn StringData* DString.data(self) @inline @private +fn StringData* DString.data(self) @inline { return (StringData*)self; } diff --git a/lib/std/core/mem_allocator.c3 b/lib/std/core/mem_allocator.c3 index a1afcd57d..abf7d846b 100644 --- a/lib/std/core/mem_allocator.c3 +++ b/lib/std/core/mem_allocator.c3 @@ -404,6 +404,28 @@ macro void*? @aligned_alloc(#alloc_fn, usz bytes, usz alignment) return mem; } +<* + @require bytes > 0 + @require alignment > 0 + @require bytes <= isz.max +*> +macro void*? @aligned_alloc_fn(context, #alloc_fn, usz bytes, usz alignment) +{ + if (alignment < void*.alignof) alignment = void*.alignof; + usz header = AlignedBlock.sizeof + alignment; + usz alignsize = bytes + header; + $if $kindof(#alloc_fn(context, bytes)) == OPTIONAL: + void* data = #alloc_fn(context, alignsize)!; + $else + void* data = #alloc_fn(context, alignsize); + $endif + void* mem = mem::aligned_pointer(data + AlignedBlock.sizeof, alignment); + AlignedBlock* desc = (AlignedBlock*)mem - 1; + assert(mem > data); + *desc = { bytes, data }; + return mem; +} + struct AlignedBlock { usz len; @@ -420,6 +442,16 @@ macro void? @aligned_free(#free_fn, void* old_pointer) $endif } +macro void? @aligned_free_fn(context, #free_fn, void* old_pointer) +{ + AlignedBlock* desc = (AlignedBlock*)old_pointer - 1; + $if $kindof(#free_fn(context, desc.start)) == OPTIONAL: + #free_fn(context, desc.start)!; + $else + #free_fn(context, desc.start); + $endif +} + <* @require bytes > 0 @require alignment > 0 @@ -438,6 +470,23 @@ macro void*? @aligned_realloc(#calloc_fn, #free_fn, void* old_pointer, usz bytes return new_data; } +<* + @require bytes > 0 + @require alignment > 0 +*> +macro void*? @aligned_realloc_fn(context, #calloc_fn, #free_fn, void* old_pointer, usz bytes, usz alignment) +{ + AlignedBlock* desc = (AlignedBlock*)old_pointer - 1; + void* data_start = desc.start; + void* new_data = @aligned_alloc_fn(context, #calloc_fn, bytes, alignment)!; + mem::copy(new_data, old_pointer, desc.len < bytes ? desc.len : bytes, 1, 1); + $if $kindof(#free_fn(context, data_start)) == OPTIONAL: + #free_fn(context, data_start)!; + $else + #free_fn(context, data_start); + $endif + return new_data; +} // All allocators alias mem @builtin = thread_allocator ; diff --git a/lib/std/core/mem_mempool.c3 b/lib/std/core/mem_mempool.c3 index 24e29a112..be366fffd 100644 --- a/lib/std/core/mem_mempool.c3 +++ b/lib/std/core/mem_mempool.c3 @@ -54,7 +54,7 @@ struct FixedBlockPool @require calculate_actual_capacity(capacity, block_size) * block_size >= block_size : "Total memory would overflow" *> -macro FixedBlockPool* FixedBlockPool.init(&self, Allocator allocator, usz block_size, usz capacity = INITIAL_CAPACITY, usz alignment = 0) +fn FixedBlockPool* FixedBlockPool.init(&self, Allocator allocator, usz block_size, usz capacity = INITIAL_CAPACITY, usz alignment = 0) { self.allocator = allocator; self.tail = &self.head; @@ -64,7 +64,7 @@ macro FixedBlockPool* FixedBlockPool.init(&self, Allocator allocator, usz block_ self.alignment = allocator::alignment_for_allocation(alignment); self.page_size = capacity * self.block_size; assert(self.page_size >= self.block_size, "Total memory would overflow %d %d", block_size, capacity); - self.head.buffer = self.allocate_page(); + self.head.buffer = fixedblockpool_allocate_page(self); $if env::COMPILER_SAFE_MODE && env::ADDRESS_SANITIZER: asan::poison_memory_region(self.head.buffer, self.page_size); $endif @@ -119,7 +119,7 @@ fn void FixedBlockPool.free(&self) $if env::COMPILER_SAFE_MODE && env::ADDRESS_SANITIZER: asan::unpoison_memory_region(self.head.buffer, self.page_size); $endif - self.free_page(self.head.buffer); + fixedblockpool_free_page(self, self.head.buffer); FixedBlockPoolNode* iter = self.head.next; while (iter) @@ -127,7 +127,7 @@ fn void FixedBlockPool.free(&self) $if env::COMPILER_SAFE_MODE && env::ADDRESS_SANITIZER: asan::unpoison_memory_region(iter.buffer, self.page_size); $endif - self.free_page(iter.buffer); + fixedblockpool_free_page(self, iter.buffer); FixedBlockPoolNode* current = iter; iter = iter.next; allocator::free(self.allocator, current); @@ -158,7 +158,7 @@ fn void* FixedBlockPool.alloc(&self) } void* end = self.tail.buffer + (self.tail.capacity * self.block_size); - if (self.next_free >= end) self.new_node(); + if (self.next_free >= end) fixedblockpool_new_node(self); void* ptr = self.next_free; self.next_free += self.block_size; $if env::COMPILER_SAFE_MODE && env::ADDRESS_SANITIZER: @@ -172,7 +172,7 @@ fn void* FixedBlockPool.alloc(&self) Deallocate a block from the block pool @require self.initialized : "The block pool must be initialized" - @require self.check_ptr(ptr) : "The pointer should be part of the pool" + @require fixedblockpool_check_ptr(self, ptr) : "The pointer should be part of the pool" *> fn void FixedBlockPool.dealloc(&self, void* ptr) { @@ -193,7 +193,7 @@ fn void FixedBlockPool.dealloc(&self, void* ptr) <* @require self.initialized : "The block pool must be initialized" *> -fn bool FixedBlockPool.check_ptr(&self, void *ptr) @local +fn bool fixedblockpool_check_ptr(FixedBlockPool* self, void *ptr) @local { FixedBlockPoolNode* iter = &self.head; @@ -210,10 +210,10 @@ fn bool FixedBlockPool.check_ptr(&self, void *ptr) @local <* @require self.grow_capacity > 0 : "How many blocks will it store" *> -fn void FixedBlockPool.new_node(&self) @local +fn void fixedblockpool_new_node(FixedBlockPool* self) @local { FixedBlockPoolNode* node = allocator::new(self.allocator, FixedBlockPoolNode); - node.buffer = self.allocate_page(); + node.buffer = fixedblockpool_allocate_page(self); $if env::COMPILER_SAFE_MODE && env::ADDRESS_SANITIZER: asan::poison_memory_region(node.buffer, self.page_size); $endif @@ -224,14 +224,14 @@ fn void FixedBlockPool.new_node(&self) @local self.allocated += node.capacity; } -macro void* FixedBlockPool.allocate_page(&self) @private +macro void* fixedblockpool_allocate_page(FixedBlockPool* self) @private { return self.alignment > mem::DEFAULT_MEM_ALIGNMENT ? allocator::calloc_aligned(self.allocator, self.page_size, self.alignment)!! : allocator::calloc(self.allocator, self.page_size); } -macro void FixedBlockPool.free_page(&self, void* page) @private +macro void fixedblockpool_free_page(FixedBlockPool* self, void* page) @private { if (self.alignment > mem::DEFAULT_MEM_ALIGNMENT) { diff --git a/lib/std/core/os/mem_vm.c3 b/lib/std/core/os/mem_vm.c3 index 09b7e08af..617eef4d0 100644 --- a/lib/std/core/os/mem_vm.c3 +++ b/lib/std/core/os/mem_vm.c3 @@ -321,7 +321,7 @@ fn void? VirtualMemory.destroy(&self) return release(self.ptr, self.size); } -fn CInt VirtualMemoryAccess.to_posix(self) @if(env::POSIX) @private +fn CInt VirtualMemoryAccess.to_posix(self) @if(env::POSIX) { switch (self) { @@ -336,7 +336,7 @@ fn CInt VirtualMemoryAccess.to_posix(self) @if(env::POSIX) @private } } -fn Win32_Protect VirtualMemoryAccess.to_win32(self) @if(env::WIN32) @private +fn Win32_Protect VirtualMemoryAccess.to_win32(self) @if(env::WIN32) { switch (self) { diff --git a/lib/std/crypto/chacha20.c3 b/lib/std/crypto/chacha20.c3 index 599b3bc74..50984bfb8 100644 --- a/lib/std/crypto/chacha20.c3 +++ b/lib/std/crypto/chacha20.c3 @@ -63,7 +63,7 @@ macro quarter_round(uint* x, int a, int b, int c, int d) @local } <* Process the next (or final) chunk of ingested data. *> -fn void ChaCha20.mutate_keystream(&self) @local @inline +fn void chacha20_mutate_keystream(ChaCha20* self) @local @inline { self.key_stream[..] = self.state[..]; @@ -137,7 +137,7 @@ fn void ChaCha20.transform(&self, char[] data) for (usz x = offset; data.len >= BLOCK_SIZE; data = data[BLOCK_SIZE..], x = offset) { - self.mutate_keystream(); + chacha20_mutate_keystream(self); if (offset) foreach (i, &b : data[:offset]) *b ^= key_stream[i]; char[] aligned_data = data[offset..]; for (; x <= (BLOCK_SIZE - usz.sizeof); x += usz.sizeof) @@ -150,7 +150,7 @@ fn void ChaCha20.transform(&self, char[] data) // 3. Process any remaining bytes. if (data.len > 0) { - self.mutate_keystream(); + chacha20_mutate_keystream(self); for (usz i = 0; i < data.len; i++) data[i] ^= key_stream[i]; self.position = data.len; } diff --git a/lib/std/crypto/ed25519.c3 b/lib/std/crypto/ed25519.c3 index d607ceff6..099d9eac3 100644 --- a/lib/std/crypto/ed25519.c3 +++ b/lib/std/crypto/ed25519.c3 @@ -567,7 +567,7 @@ fn F25519Int F25519Int.inv(&s) @param [&in] s *> -fn F25519Int F25519Int.pow_2523(&s) @local +fn F25519Int pow_2523(F25519Int* s) @local { F25519Int r = *s; @@ -587,7 +587,7 @@ fn F25519Int F25519Int.pow_2523(&s) @local fn F25519Int F25519Int.sqrt(&s) { F25519Int twice = s.mul_s(2); - F25519Int pow = twice.pow_2523(); + F25519Int pow = pow_2523(&twice); return (twice * pow * pow - ONE) * s * pow; } diff --git a/lib/std/experimental/FrameScheduler.c3 b/lib/std/experimental/FrameScheduler.c3 index 5e029a996..94a7f7531 100644 --- a/lib/std/experimental/FrameScheduler.c3 +++ b/lib/std/experimental/FrameScheduler.c3 @@ -7,7 +7,7 @@ struct DelayedSchedulerEvent @local Clock execution_time; } -fn int DelayedSchedulerEvent.compare_to(self, DelayedSchedulerEvent other) @local +fn int DelayedSchedulerEvent.compare_to(self, DelayedSchedulerEvent other) { switch { diff --git a/lib/std/hash/blake2.c3 b/lib/std/hash/blake2.c3 index 6228a7452..edc5e5c67 100644 --- a/lib/std/hash/blake2.c3 +++ b/lib/std/hash/blake2.c3 @@ -49,43 +49,43 @@ macro @round(r, m, $s, #v) @local @g(r, m, $s, 7, #v[ 3], #v[ 4], #v[ 9], #v[14]); } -macro @common_compress(#instance, $rounds, $iv, $sigma, block) @local +macro common_compress(instance, $rounds, $iv, $sigma, block) @local { - $typeof(#instance.h[0])[16] m, v; + $typeof(instance.h[0])[16] m, v; ((char*)&m)[:$sizeof(block)] = block[..]; - v[:8] = #instance.h[..]; + v[:8] = instance.h[..]; v[ 8] = $iv[0]; v[ 9] = $iv[1]; v[10] = $iv[2]; v[11] = $iv[3]; - v[12] = $iv[4] ^ #instance.t[0]; - v[13] = $iv[5] ^ #instance.t[1]; - v[14] = $iv[6] ^ #instance.f[0]; - v[15] = $iv[7] ^ #instance.f[1]; + v[12] = $iv[4] ^ instance.t[0]; + v[13] = $iv[5] ^ instance.t[1]; + v[14] = $iv[6] ^ instance.f[0]; + v[15] = $iv[7] ^ instance.f[1]; $for usz $i = 0; $i < $rounds; $i++: @round($i, m, $sigma, v); $endfor $for usz $i = 0; $i < 8; $i++: - #instance.h[$i] ^= v[$i] ^ v[$i + 8]; + instance.h[$i] ^= v[$i] ^ v[$i + 8]; $endfor } -macro @add_ctr(#instance, usz amount) @local +macro _add_ctr(instance, usz amount) @local { - #instance.t[0] += ($typeof(#instance.t[0]))amount; - #instance.t[1] += ($typeof(#instance.t[0]))(#instance.t[0] < amount); // adds 1 on overflow of [0] + instance.t[0] += ($typeof(instance.t[0]))amount; + instance.t[1] += ($typeof(instance.t[0]))(instance.t[0] < amount); // adds 1 on overflow of [0] } -macro @common_init(#instance, $ParamType, $iv, usz out_len, char[] key = {}, char[] salt = {}, char[] personal = {}) @local +macro common_init(instance, $ParamType, $iv, usz out_len, char[] key = {}, char[] salt = {}, char[] personal = {}) @local { - mem::zero_volatile(@as_char_view(*#instance)); // explicitly because habits around hash init usually involve @noinit + mem::zero_volatile(@as_char_view(*instance)); // explicitly because habits around hash init usually involve @noinit - #instance.h[..] = $iv[..]; - #instance.outlen = out_len; + instance.h[..] = $iv[..]; + instance.outlen = out_len; $ParamType p = { .digest_length = (char)out_len, @@ -96,59 +96,60 @@ macro @common_init(#instance, $ParamType, $iv, usz out_len, char[] key = {}, cha if (salt.len) p.salt[:salt.len] = salt[..]; if (personal.len) p.personal[:personal.len] = personal[..]; - array::@zip_into(((char*)&#instance.h)[:$sizeof(p)], ((char*)&p)[:$sizeof(p)], fn (a, b) => a ^ b); // bytes(self.h) ^= bytes(p) + array::@zip_into(((char*)&instance.h)[:$sizeof(p)], ((char*)&p)[:$sizeof(p)], fn (a, b) => a ^ b); // bytes(self.h) ^= bytes(p) if (key.len) { char[$sizeof($iv[0])*16] dummy = {}; dummy[:key.len] = key[..]; - #instance.update(dummy[..]); // consume a FULL block + instance.update(dummy[..]); // consume a FULL block mem::zero_volatile(dummy[..]); // do not optimize clearing this from the stack } } -macro @common_update(#instance, $block_size, char[] data) @local +macro common_update(instance, $block_size, char[] data) @local { if (@unlikely(!data.len)) return; - usz fill = $block_size - #instance.buflen; + usz fill = $block_size - instance.buflen; if (data.len > fill) { - #instance.buf[#instance.buflen:fill] = data[:fill]; - #instance.buflen = 0; + instance.buf[instance.buflen:fill] = data[:fill]; + instance.buflen = 0; - @add_ctr(#instance, $block_size); - #instance.compress(#instance.buf); + _add_ctr(instance, $block_size); + instance._compress(instance.buf); data = data[fill..]; for (; data.len > $block_size; data = data[$block_size..]) { - @add_ctr(#instance, $block_size); - #instance.compress(data[:$block_size]); + _add_ctr(instance, $block_size); + instance._compress(data[:$block_size]); } } - #instance.buf[#instance.buflen:data.len] = data[..]; - #instance.buflen += data.len; + instance.buf[instance.buflen:data.len] = data[..]; + instance.buflen += data.len; } -macro @common_final(#instance, $output_length) @local +macro common_final(instance, $output_length) @local { char[$output_length] result = {}; - if ($output_length != #instance.outlen) return result; + if ($output_length != instance.outlen) return result; - @add_ctr(#instance, #instance.buflen); - if (#instance.f[0]) return result; // technically an error return + _add_ctr(instance, instance.buflen); + if (instance.f[0]) return result; // technically an error return - if (#instance.last_node) #instance.f[1] = $typeof(#instance.h[0]).max; - #instance.f[0] = $typeof(#instance.h[0]).max; + var $max = $typeof(instance.h[0]).max; + if (instance.last_node) instance.f[1] = $max; + instance.f[0] = $max; - mem::zero_volatile(#instance.buf[#instance.buflen..]); // pad buffer with zeroes - #instance.compress(#instance.buf); + mem::zero_volatile(instance.buf[instance.buflen..]); // pad buffer with zeroes + instance._compress(instance.buf); - defer mem::zero_volatile(@as_char_view(*#instance)); // destroy the current context implicitly + defer mem::zero_volatile(@as_char_view(*instance)); // destroy the current context implicitly - result[:#instance.outlen] = @as_char_view(#instance.h)[:#instance.outlen]; + result[:instance.outlen] = @as_char_view(instance.h)[:instance.outlen]; return result; } @@ -244,13 +245,13 @@ alias b_512 = blake2b_512; @require !personal.ptr || (personal.len > 0 && personal.len <= BLAKE2B_PERSONALBYTES) : "A specified personalization's length must be within the proper range." *> fn void Blake2b.init(&self, usz out_len, char[] key = {}, char[] salt = {}, char[] personal = {}) - => @common_init(self, Blake2bParam, BLAKE2B_IV, out_len, key, salt, personal); + => common_init(self, Blake2bParam, BLAKE2B_IV, out_len, key, salt, personal); <* Core compression inline function for Blake2b. *> -fn void Blake2b.compress(&self, char[BLAKE2B_BLOCKBYTES] block) @local @inline - => @common_compress(self, 12, BLAKE2B_IV, BLAKE2B_SIGMA, block); +fn void Blake2b._compress(&self, char[BLAKE2B_BLOCKBYTES] block) @inline + => common_compress(self, 12, BLAKE2B_IV, BLAKE2B_SIGMA, block); <* Add more data to the hash context or stream. @@ -258,7 +259,7 @@ fn void Blake2b.compress(&self, char[BLAKE2B_BLOCKBYTES] block) @local @inline @param[in] data : "The data to ingest into the hash context." *> fn void Blake2b.update(&self, char[] data) - => @common_update(self, BLAKE2B_BLOCKBYTES, data); + => common_update(self, BLAKE2B_BLOCKBYTES, data); <* Finalize the hash context and return the hash result at the given size. @@ -267,9 +268,12 @@ fn void Blake2b.update(&self, char[] data) @require $output_length == self.outlen : "The specified compile-time output size MUST be equal to the initialized output size." *> -macro char[*] Blake2b.final(&self, $output_length) - => @common_final(self, $output_length); +macro char[*] Blake2b.final(&self, $output_length) => _blake2b_final{$output_length}(self); +fn char[OUTPUT_LENGTH] _blake2b_final(Blake2b* self) @local +{ + return common_final(self, OUTPUT_LENGTH); +} // ====================================================================================== // BEGIN Blake2s contents. Do not separate this from Blake2b: there's not really a point. @@ -356,13 +360,13 @@ alias s_256 = blake2s_256; @require !personal.ptr || (personal.len > 0 && personal.len <= BLAKE2B_PERSONALBYTES) : "A specified personalization's length must be within the proper range." *> fn void Blake2s.init(&self, usz out_len, char[] key = {}, char[] salt = {}, char[] personal = {}) - => @common_init(self, Blake2sParam, BLAKE2S_IV, out_len, key, salt, personal); + => common_init(self, Blake2sParam, BLAKE2S_IV, out_len, key, salt, personal); <* Core compression inline function for Blake2s. *> -fn void Blake2s.compress(&self, char[BLAKE2S_BLOCKBYTES] block) @local @inline - => @common_compress(self, 10, BLAKE2S_IV, BLAKE2S_SIGMA, block); +fn void Blake2s._compress(&self, char[BLAKE2S_BLOCKBYTES] block) @inline + => common_compress(self, 10, BLAKE2S_IV, BLAKE2S_SIGMA, block); <* Add more data to the hash context or stream. @@ -370,7 +374,7 @@ fn void Blake2s.compress(&self, char[BLAKE2S_BLOCKBYTES] block) @local @inline @param[in] data : "The data to ingest into the hash context." *> fn void Blake2s.update(&self, char[] data) - => @common_update(self, BLAKE2S_BLOCKBYTES, data); + => common_update(self, BLAKE2S_BLOCKBYTES, data); <* Finalize the hash context and return the hash result at the given size. @@ -380,4 +384,4 @@ fn void Blake2s.update(&self, char[] data) @require $output_length == self.outlen : "The specified compile-time output size MUST be equal to the initialized output size." *> macro char[*] Blake2s.final(&self, $output_length) - => @common_final(self, $output_length); + => common_final(self, $output_length); diff --git a/lib/std/hash/blake3.c3 b/lib/std/hash/blake3.c3 index f0fb0ab19..570b146af 100644 --- a/lib/std/hash/blake3.c3 +++ b/lib/std/hash/blake3.c3 @@ -246,7 +246,7 @@ fn void Blake3.init(&self, char[] key = {}, char explicit_flags = 0) <* Reset the state of the hashing context, in case it should be reused without reloading the key value. *> -fn void Blake3.reset(&self) @local @inline +fn void _reset(Blake3* self) @local @inline { self.chunk.reset(self.key[..], 0); self.cv_stack_len = 0; @@ -255,7 +255,7 @@ fn void Blake3.reset(&self) @local @inline <* Private function to merge tree results. *> -fn void Blake3.merge_cv_stack(&self, ulong total_len) @local @inline +fn void _merge_cv_stack(Blake3* self, ulong total_len) @local @inline { usz post_merge_stack_len = (usz)@popcnt(total_len); for (; self.cv_stack_len > post_merge_stack_len; self.cv_stack_len--) @@ -269,9 +269,9 @@ fn void Blake3.merge_cv_stack(&self, ulong total_len) @local @inline <* Private function to add a new tree onto the stack. *> -fn void Blake3.push_cv(&self, char* new_cv, ulong chunk_counter) @local @inline +fn void Blake3.push_cv(&self, char* new_cv, ulong chunk_counter) @inline { - self.merge_cv_stack(chunk_counter); + _merge_cv_stack(self, chunk_counter); self.cv_stack[self.cv_stack_len * OUT_SIZE : OUT_SIZE] = new_cv[:OUT_SIZE]; self.cv_stack_len++; } @@ -334,7 +334,7 @@ fn void Blake3.update(&self, char[] input, bool use_tbb = false) if (input.len > 0) { self.chunk.update(input); - self.merge_cv_stack(self.chunk.chunk_counter); + _merge_cv_stack(self, self.chunk.chunk_counter); } } @@ -400,7 +400,7 @@ fn void Blake3.destroy(&self) @inline @param [in] key @param flags *> -fn void Blake3ChunkState.init(&self, uint[] key, char flags) @local @inline +fn void Blake3ChunkState.init(&self, uint[] key, char flags) @inline { mem::zero_volatile(@as_char_view(*self)); self.cv[..] = key[..]; @@ -413,7 +413,7 @@ fn void Blake3ChunkState.init(&self, uint[] key, char flags) @local @inline @param [in] key @param chunk_counter *> -fn void Blake3ChunkState.reset(&self, uint[] key, ulong chunk_counter) @local @inline +fn void Blake3ChunkState.reset(&self, uint[] key, ulong chunk_counter) @inline { self.init(key, self.flags); // maintain its own flags self.chunk_counter = chunk_counter; // update chunk counter @@ -422,7 +422,7 @@ fn void Blake3ChunkState.reset(&self, uint[] key, ulong chunk_counter) @local @i <* Get bytes length of consumed data. *> -fn usz Blake3ChunkState.len(&self) @operator(len) @local @inline +fn usz Blake3ChunkState.len(&self) @operator(len) @inline => (BLOCK_SIZE * (usz)self.blocks_compressed) + (usz)self.buf_len; <* @@ -430,7 +430,7 @@ fn usz Blake3ChunkState.len(&self) @operator(len) @local @inline @param [in] data : "Data to ingest." *> -fn usz Blake3ChunkState.fill_buf(&self, char[] data) @local @inline +fn usz Blake3ChunkState.fill_buf(&self, char[] data) @inline { usz take = min(BLOCK_SIZE - (usz)self.buf_len, data.len); self.buf[self.buf_len:take] = data[:take]; @@ -441,7 +441,7 @@ fn usz Blake3ChunkState.fill_buf(&self, char[] data) @local @inline <* Determine whether to set the CHUNK_START flag. *> -fn char Blake3ChunkState.maybe_start_flag(&self) @local @inline +fn char Blake3ChunkState.maybe_start_flag(&self) @inline => !self.blocks_compressed ? Blake3Flags.CHUNK_START : 0; <* @@ -449,7 +449,7 @@ fn char Blake3ChunkState.maybe_start_flag(&self) @local @inline @param [in] input : "Incoming bytes to update with." *> -fn void Blake3ChunkState.update(&self, char[] input) @local +fn void Blake3ChunkState.update(&self, char[] input) { if (self.buf_len) { @@ -473,7 +473,7 @@ fn void Blake3ChunkState.update(&self, char[] input) @local <* Convert the chunk state to an "output" type with the right flags. *> -fn Blake3Output Blake3ChunkState.output(&self) @local @inline +fn Blake3Output Blake3ChunkState.output(&self) @inline => make_output(self.cv[..], &self.buf, self.buf_len, self.chunk_counter, self.flags | self.maybe_start_flag() | Blake3Flags.CHUNK_END); <* @@ -511,7 +511,7 @@ macro Blake3Output parent_output(char* block, uint[] key, char flags) @local @param [&inout] cv *> -macro void Blake3Output.chaining_value(&self, char* cv) @local +macro void Blake3Output.chaining_value(&self, char* cv) { uint[KEY_SIZE_WORDS] cv_words; cv_words[..] = self.input_cv[..]; @@ -525,7 +525,7 @@ macro void Blake3Output.chaining_value(&self, char* cv) @local @param seek @param [inout] into *> -fn void Blake3Output.root_bytes(&self, usz seek, char[] into) @local +fn void Blake3Output.root_bytes(&self, usz seek, char[] into) { if (!into.len) return; diff --git a/lib/std/hash/gost/streebog.c3 b/lib/std/hash/gost/streebog.c3 index 8e8752696..367de4062 100644 --- a/lib/std/hash/gost/streebog.c3 +++ b/lib/std/hash/gost/streebog.c3 @@ -147,13 +147,13 @@ fn void Streebog.update(&self, char[] data) macro char[*] Streebog.final(&self, StreebogLength $hash_size) { char[$hash_size] result; - self._final_private(); + streebog_final_private(self); defer mem::zero_volatile(@as_char_view(*self)); // implicitly clear the structure when finalized result[..] = @as_char_view(self.h)[(BLOCK_SIZE - $hash_size)..]; return result; } -fn void Streebog._final_private(&self) @local +fn void streebog_final_private(Streebog* self) @local { ulong[8] unprocessed_bits_count; usz index = self.index >> 3; diff --git a/lib/std/hash/poly1305.c3 b/lib/std/hash/poly1305.c3 index c67d1ec5f..5fe751aad 100644 --- a/lib/std/hash/poly1305.c3 +++ b/lib/std/hash/poly1305.c3 @@ -86,14 +86,14 @@ fn void Poly1305.update(&self, char[] input) } // ingest up to a block size to finish the partial, then advance the slice ptr self.temp[self.num:rem] = input[:rem]; - self.blocks(self.temp[..]); + _blocks(self, self.temp[..]); input = input[rem..]; } usz even_length = input.len - (input.len % BLOCK_SIZE); if (even_length >= BLOCK_SIZE) { - self.blocks(input[:even_length]); // consume blocks + _blocks(self, input[:even_length]); // consume blocks input = input[even_length..]; // scroll to end (remainder) } @@ -109,7 +109,7 @@ fn char[TAG_SIZE] Poly1305.final(&self) { self.temp[self.num++] = 1; // partial blocks must end with 0x01 self.temp[self.num..] = {}; // explicit zeros on the rest - self.blocks(self.temp[..], 0); // chomp + _blocks(self, self.temp[..], 0); // chomp } uint128 t = (uint128)self.h[0] + 5; @@ -135,7 +135,7 @@ fn char[TAG_SIZE] Poly1305.final(&self) } -fn void Poly1305.blocks(&self, char[] input, ulong pad_bit = 1) @local +fn void _blocks(Poly1305* self, char[] input, ulong pad_bit = 1) @local { for (; input.len >= BLOCK_SIZE; input = input[BLOCK_SIZE..]) { diff --git a/lib/std/hash/sha256.c3 b/lib/std/hash/sha256.c3 index 706f1d55f..410175d27 100644 --- a/lib/std/hash/sha256.c3 +++ b/lib/std/hash/sha256.c3 @@ -68,18 +68,18 @@ fn void Sha256.update(&self, char[] data) usz len = min(BLOCK_SIZE - buffer_pos, data.len); self.buffer[buffer_pos:len] = data[:len]; data = data[len..]; - if (buffer_pos + len == BLOCK_SIZE) self.transform(); + if (buffer_pos + len == BLOCK_SIZE) _transform(self); } // When the data pointer is aligned, we can disregard unaligned loading in the `transform` macro. // We do this here from the outer call to reduce the expense of checking alignment on every single block. if (0 == (usz)data.ptr % usz.sizeof) { - for (; data.len >= BLOCK_SIZE; data = data[BLOCK_SIZE..]) self.transform((uint*)data.ptr); + for (; data.len >= BLOCK_SIZE; data = data[BLOCK_SIZE..]) _transform(self, (uint*)data.ptr); } else { - for (; data.len >= BLOCK_SIZE; data = data[BLOCK_SIZE..]) self.transform_unaligned((uint*)data.ptr); + for (; data.len >= BLOCK_SIZE; data = data[BLOCK_SIZE..]) _transform_unaligned(self, (uint*)data.ptr); } // Leftover data just gets stored away for the next update or final. @@ -102,7 +102,7 @@ fn char[HASH_SIZE] Sha256.final(&self) if (i > BLOCK_SIZE - 8) { self.buffer[i..] = 0x00; - self.transform(); + _transform(self); i = 0; // Reset buffer index after transformation } @@ -111,7 +111,7 @@ fn char[HASH_SIZE] Sha256.final(&self) // Append the bitcount in big-endian format *(ulong*)(&self.buffer[BLOCK_SIZE - 8]) = env::BIG_ENDIAN ??? self.bitcount : bswap(self.bitcount); - self.transform(); + _transform(self); // Convert state to the final hash foreach (x, s : self.state) *(uint*)(&hash[x * uint.sizeof]) = env::BIG_ENDIAN ??? s : bswap(s); @@ -121,10 +121,10 @@ fn char[HASH_SIZE] Sha256.final(&self) // These wrappers are necessary to significantly reduce code generation from macro expansions. // Note that transformations on `self.buffer` (when incoming == null) should always be aligned. -fn void Sha256.transform(&self, uint* incoming = null) @local @noinline => self.do_transform(incoming, true); -fn void Sha256.transform_unaligned(&self, uint* incoming = null) @local @noinline => self.do_transform(incoming, false); +fn void _transform(Sha256* self, uint* incoming = null) @local @noinline => _do_transform(self, incoming, true); +fn void _transform_unaligned(Sha256* self, uint* incoming = null) @local @noinline => _do_transform(self, incoming, false); -macro Sha256.do_transform(&self, uint* incoming = null, bool $aligned = true) @local +macro _do_transform(Sha256* self, uint* incoming = null, bool $aligned = true) @local { uint a, b, c, d, e, f, g, h, t1, t2 @noinit; uint[64] m @noinit; diff --git a/lib/std/hash/siphash.c3 b/lib/std/hash/siphash.c3 index 2c358f328..bcd2cc0e8 100644 --- a/lib/std/hash/siphash.c3 +++ b/lib/std/hash/siphash.c3 @@ -100,7 +100,7 @@ fn void SipHash.update(&self, char[] data) self.v[3] ^= self.m; $for var $i = 0; $i < BLOCK_ROUNDS; ++$i : // unrolled loop - self.round(); + siphash_round(self); $endfor self.v[0] ^= self.m; @@ -123,7 +123,7 @@ fn OutType SipHash.final(&self) $endif $for var $i = 0; $i < FINALIZE_ROUNDS; ++$i : // unrolled loop - self.round(); + siphash_round(self); $endfor $if OutType.typeid == ulong.typeid : @@ -134,7 +134,7 @@ fn OutType SipHash.final(&self) self.v[1] ^= 0xDD; $for var $i = 0; $i < FINALIZE_ROUNDS; ++$i : // unrolled loop - self.round(); + siphash_round(self); $endfor return lo | ((uint128)(self.v[0] ^ self.v[1] ^ self.v[2] ^ self.v[3]) << 64); @@ -142,7 +142,7 @@ fn OutType SipHash.final(&self) } -fn void SipHash.round(&self) @local +fn void siphash_round(SipHash* self) @local { self.v[0] += self.v[1]; self.v[1] = self.v[1].rotl(13); diff --git a/lib/std/hash/whirlpool/whirlpool.c3 b/lib/std/hash/whirlpool/whirlpool.c3 index 4101b42e4..e95302a61 100644 --- a/lib/std/hash/whirlpool/whirlpool.c3 +++ b/lib/std/hash/whirlpool/whirlpool.c3 @@ -66,14 +66,14 @@ fn void Whirlpool.update(&self, char[] data) // If the algorithm is finalized during a 'partial' block, it has its own padding to fill the remaining gap. if (data.len < to_pad) return; - self.process_block(&self.block); + _process_block(self, &self.block); data = data[to_pad..]; } // Digest blocks wholesale. while (data.len >= BLOCK_SIZE) { - self.process_block(data); + _process_block(self, data); data = (data.len > BLOCK_SIZE) ? data[BLOCK_SIZE..] : {}; } @@ -100,7 +100,7 @@ fn char[HASH_SIZE] Whirlpool.final(&self) { if (remainder < 64) self.block[remainder..63] = 0x00; - self.process_block(&self.block); + _process_block(self, &self.block); remainder = 0; } @@ -113,7 +113,7 @@ fn char[HASH_SIZE] Whirlpool.final(&self) self.block_128[3] = $$bswap(self.counter_low << 3); // Process the final block. - self.process_block(&self.block); + _process_block(self, &self.block); // Each ulong in the resultant hash should be bit-swapped before the final return. char[HASH_SIZE] hash @align(ulong.alignof); @@ -153,7 +153,7 @@ const ulong[10] RC @private = { }; const ROUNDS = 10; -fn void Whirlpool.process_block(&self, char* block) @local +fn void _process_block(Whirlpool* self, char* block) @local { ulong[2 * 8] k; // key ulong[2 * 8] state; // state diff --git a/lib/std/io/formatter.c3 b/lib/std/io/formatter.c3 index 8909b3a93..f899aed4c 100644 --- a/lib/std/io/formatter.c3 +++ b/lib/std/io/formatter.c3 @@ -91,16 +91,7 @@ fn void Formatter.init(&self, OutputFn out_fn, void* data = null) *self = { .data = data, .out_fn = out_fn}; } -fn usz? Formatter.out(&self, char c) @private -{ - if (catch err = self.out_fn(self.data, c)) - { - if (self.first_fault) return self.first_fault~; - self.first_fault = err; - return err~; - } - return 1; -} + fn usz? Formatter.print_with_function(&self, Printable arg) { @@ -115,7 +106,7 @@ fn usz? Formatter.print_with_function(&self, Printable arg) self.width = old_width; self.prec = old_prec; } - if (!arg) return self.out_substr("(null)"); + if (!arg) return formatter_out_substr(self, "(null)"); return arg.to_format(self); } if (&arg.to_constant_string) @@ -129,161 +120,12 @@ fn usz? Formatter.print_with_function(&self, Printable arg) self.width = old_width; self.prec = old_prec; } - if (!arg) return self.out_substr("(null)"); - return self.out_substr(arg.to_constant_string()); + if (!arg) return formatter_out_substr(self, "(null)"); + return formatter_out_substr(self, arg.to_constant_string()); } return NOT_FOUND~; } -fn usz? Formatter.out_unknown(&self, String category, any arg) @private -{ - return self.out_substr("<") + self.out_substr(category) + self.out_substr(" type:") + self.ntoa((iptr)arg.type, false, 16) + self.out_substr(", addr:") + self.ntoa((iptr)arg.ptr, false, 16) + self.out_substr(">"); -} -fn usz? Formatter.out_collection(&self, any arg, String open, String close) @private -{ - typeid inner = arg.type.inner; - if (inner == void.typeid) inner = char.typeid; - usz size = inner.sizeof; - - usz alen; - void* data_ptr; - if (arg.type.kindof == SLICE) - { - String* temp = arg.ptr; - data_ptr = temp.ptr; - alen = temp.len; - } - else - { - data_ptr = arg.ptr; - alen = arg.type.len; - } - - PrintFlags flags = self.flags; - uint width = self.width; - defer - { - self.flags = flags; - self.width = width; - } - self.flags = {}; - self.width = 0; - - usz len = self.out_substr(open)!; - for (usz i = 0; i < alen; i++) - { - if (i != 0) len += self.out_substr(", ")!; - len += self.out_str(any_make(data_ptr, inner))!; - data_ptr += size; - } - len += self.out_substr(close)!; - return len; -} - -fn usz? Formatter.out_str(&self, any arg) @private -{ - switch (arg.type.kindof) - { - case VOID: - return self.out_substr("void"); - case FAULT: - fault f = *(fault*)arg.ptr; - return self.out_substr(f ? f.nameof : "(empty-fault)"); - case INTERFACE: - any a = *(any*)arg; - return a ? self.out_str(a) : self.out_substr("(empty-interface)"); - case ANY: - any a = *(any*)arg; - return a ? self.out_str(a) : self.out_substr("(empty-any)"); - case OPTIONAL: - unreachable(); - case SIGNED_INT: - case UNSIGNED_INT: - case FLOAT: - case FUNC: - case POINTER: - PrintFlags flags = self.flags; - uint width = self.width; - defer - { - self.flags = flags; - self.width = width; - } - self.flags = {}; - self.width = 0; - switch (arg.type.kindof) - { - case SIGNED_INT: - case UNSIGNED_INT: - return self.ntoa_any(arg, 10) ?? self.out_substr(""); - case FLOAT: - return self.ftoa(float_from_any(arg)) ?? self.out_substr("ERR"); - case FUNC: - case POINTER: - if (arg.type.kindof == POINTER && arg.type.inner != void.typeid) - { - void** pointer = arg.ptr; - any deref = any_make(*pointer, arg.type.inner); - usz? n = self.print_with_function((Printable)deref); - if (try n) return n; - if (@catch(n) != NOT_FOUND) n!; - } - return self.out_substr("0x")! + self.ntoa_any(arg, 16); - default: - unreachable(); - } - case BOOL: - return self.out_substr(*(bool*)arg.ptr ? "true" : "false"); - default: - } - usz? n = self.print_with_function((Printable)arg); - if (try n) return n; - if (@catch(n) != NOT_FOUND) n!; - switch (arg.type.kindof) - { - case TYPEID: - return self.out_substr("typeid[")! + self.ntoa((iptr)*(typeid*)arg, false, 16)! + self.out_substr("]")!; - case ENUM: - usz i = types::any_to_enum_ordinal(arg, usz)!!; - assert(i < arg.type.names.len, "Illegal enum value found, numerical value was %d.", i); - return self.out_substr(arg.type.names[i]); - case STRUCT: - return self.out_unknown("struct", arg); - case UNION: - return self.out_unknown("union", arg); - case BITSTRUCT: - return self.out_unknown("bitstruct", arg); - case CONST_ENUM: - case DISTINCT: - if (arg.type == String.typeid) - { - return self.out_substr(*(String*)arg); - } - if (arg.type == ZString.typeid) - { - return self.out_substr(*(ZString*)arg ? ((ZString*)arg).str_view() : "(null)"); - } - if (arg.type == DString.typeid) - { - return self.out_substr(*(DString*)arg ? ((DString*)arg).str_view() : "(null)"); - } - return self.out_str(arg.as_inner()); - case ARRAY: - return self.out_collection(arg, "[", "]"); - case VECTOR: - return self.out_collection(arg, "[<", ">]"); - case SLICE: - return self.out_collection(arg, "[", "]"); - case ANY: - case INTERFACE: - unreachable("Already handled"); - default: - } - return self.out_substr("Invalid type"); -} - - - fn void? out_null_fn(void* data @unused, char c @unused) @private { @@ -291,7 +133,7 @@ fn void? out_null_fn(void* data @unused, char c @unused) @private macro usz? @report_fault(Formatter* f, $fault) { - (void)f.out_substr($fault); + (void)formatter_out_substr(f, $fault); return INVALID_FORMAT~; } @@ -307,69 +149,14 @@ macro usz? @wrap_bad(Formatter* f, #action) return f.first_err(err)~; default: err = f.first_err(INVALID_ARGUMENT); - f.out_substr("")!; + formatter_out_substr(f, "")!; return err~; } } return len; } -fn usz? Formatter.out_hex_buffer(&self, any arg) @private @inline -{ - char[] out @noinit; - switch (arg.type) - { - case char[]: - case ichar[]: - out = *(char[]*)arg; - default: - if (arg.type.kindof == ARRAY && (arg.type.inner == char.typeid || arg.type.inner == ichar.typeid)) - { - out = ((char*)arg.ptr)[:arg.type.sizeof]; - break; - } - if (arg.type.kindof == POINTER) - { - // Maybe there is a more idiomatic way here - out = ((*(char**)arg.ptr))[:arg.type.inner.sizeof]; - break; - } - return self.out_substr(""); - } - usz len = out.len * 2; - usz total; - if (self.flags.left) - { - total += print_hex_chars(self, out, self.flags.uppercase)!; - total += self.pad(' ', self.width, (isz)total)!; - } - else - { - if (self.width) total += self.pad(' ', self.width, (isz)len)!; - total += print_hex_chars(self, out, self.flags.uppercase)!; - } - return total; -} -fn usz? Formatter.out_str_pad(&self, any arg) @private @inline -{ - usz total; - if (self.width && !self.flags.left) - { - OutputFn out_fn = self.out_fn; - self.out_fn = (OutputFn)&out_null_fn; - usz len = self.out_str(arg)!; - self.out_fn = out_fn; - total += self.pad(' ', self.width, (isz)len)!; - } - usz len = self.out_str(arg)!; - total += len; - if (self.flags.left) - { - total += self.pad(' ', self.width, (isz)len)!; - } - return total; -} fn usz? Formatter.vprintf(&self, String format, any[] anys) { @@ -389,7 +176,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys) if (c != '%') { // no - total_len += self.out(c)!; + total_len += self.print_char(c)!; continue; } i++; @@ -397,7 +184,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys) c = format[i]; if (c == '%') { - total_len += self.out(c)!; + total_len += self.print_char(c)!; continue; } // evaluate flags @@ -443,7 +230,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys) if (variant_index >= anys.len) { self.first_err(NOT_ENOUGH_ARGUMENTS); - total_len += self.out_substr("")!; + total_len += formatter_out_substr(self, "")!; continue; } any current = anys[variant_index++]; @@ -471,37 +258,37 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys) self.flags.uppercase = true; nextcase; case 'a': - total_len += @wrap_bad(self, self.atoa(float_from_any(current)))!; + total_len += @wrap_bad(self, formatter_atoa(self, float_from_any(current)))!; continue; case 'F' : self.flags.uppercase = true; nextcase; case 'f': - total_len += @wrap_bad(self, self.ftoa(float_from_any(current)))!; + total_len += @wrap_bad(self, formatter_ftoa(self, float_from_any(current)))!; continue; case 'E': self.flags.uppercase = true; nextcase; case 'e': - total_len += @wrap_bad(self, self.etoa(float_from_any(current)))!; + total_len += @wrap_bad(self, formatter_etoa(self, float_from_any(current)))!; continue; case 'G': self.flags.uppercase = true; nextcase; case 'g': - total_len += @wrap_bad(self, self.gtoa(float_from_any(current)))!; + total_len += @wrap_bad(self, formatter_gtoa(self, float_from_any(current)))!; continue; case 'c': - total_len += self.out_char(current)!; + total_len += formatter_out_char(self, current)!; continue; case 'H': self.flags.uppercase = true; nextcase; case 'h': - total_len += self.out_hex_buffer(current)!; + total_len += formatter_out_hex_buffer(self, current)!; continue; case 's': - total_len += self.out_str_pad(current)!; + total_len += formatter_out_str_pad(self, current)!; continue; case 'p': self.flags.zeropad = true; @@ -509,7 +296,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys) base = 16; default: self.first_err(INVALID_FORMAT); - total_len += self.out_substr("")!; + total_len += formatter_out_substr(self, "")!; continue; } if (base != 10) @@ -521,13 +308,25 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys) if (self.flags.precision) self.flags.zeropad = false; bool is_neg; - total_len += @wrap_bad(self, self.ntoa(int_from_any(current, &is_neg), is_neg, base))!; + total_len += @wrap_bad(self, formatter_ntoa(self, int_from_any(current, &is_neg), is_neg, base))!; } if (self.first_fault) return self.first_fault~; return total_len; } +fn usz? Formatter.out(&self, char c) @deprecated("Use print_char") => self.print_char(c); + +fn usz? Formatter.print_char(&self, char c) +{ + if (catch err = self.out_fn(self.data, c)) + { + if (self.first_fault) return self.first_fault~; + self.first_fault = err; + return err~; + } + return 1; +} fn usz? Formatter.print(&self, String str) { @@ -536,6 +335,6 @@ fn usz? Formatter.print(&self, String str) // use null output function self.out_fn = &out_null_fn; } - foreach (c : str) self.out(c)!; + foreach (c : str) self.print_char(c)!; return str.len; } diff --git a/lib/std/io/formatter_private.c3 b/lib/std/io/formatter_private.c3 index 9de436709..395e42fa4 100644 --- a/lib/std/io/formatter_private.c3 +++ b/lib/std/io/formatter_private.c3 @@ -13,10 +13,10 @@ fn usz? print_hex_chars(Formatter* f, char[] out, bool uppercase) @inline foreach (c : out) { char digit = c >> 4; - f.out(digit + (digit < 10 ? '0' : past_10))!; + f.print_char(digit + (digit < 10 ? '0' : past_10))!; len++; digit = c & 0xf; - f.out(digit + (digit < 10 ? '0' : past_10))!; + f.print_char(digit + (digit < 10 ? '0' : past_10))!; len++; } return len; @@ -29,10 +29,10 @@ macro fault Formatter.first_err(&self, fault f) return f; } -fn usz? Formatter.adjust(&self, usz len) @local +fn usz? formatter_adjust(Formatter* f, usz len) @local { - if (!self.flags.left) return 0; - return self.pad(' ', self.width, len); + if (!f.flags.left) return 0; + return formatter_pad(f, ' ', f.width, len); } fn uint128? int_from_any(any arg, bool *is_neg) @private @@ -156,11 +156,11 @@ fn uint simple_atoi(char* buf, usz maxlen, usz* len_ptr) @inline @private return i; } -fn usz? Formatter.out_substr(&self, String str) @private +fn usz? formatter_out_substr(Formatter* f, String str) @private { usz l = conv::utf8_codepoints(str); - uint prec = self.prec; - if (self.flags.precision && l < prec) l = prec; + uint prec = f.prec; + if (f.flags.precision && l < prec) l = prec; usz index = 0; usz chars = str.len; char* ptr = str.ptr; @@ -168,17 +168,17 @@ fn usz? Formatter.out_substr(&self, String str) @private { char c = ptr[index]; // Break if we have precision set and we ran out... - if (c & 0xC0 != 0x80 && self.flags.precision && !prec--) break; - self.out(c)!; + if (c & 0xC0 != 0x80 && f.flags.precision && !prec--) break; + f.print_char(c)!; index++; } return index; } -fn usz? Formatter.pad(&self, char c, isz width, isz len) @inline +fn usz? formatter_pad(Formatter* f, char c, isz width, isz len) @inline { isz delta = width - len; - for (isz i = 0; i < delta; i++) self.out(c)!; + for (isz i = 0; i < delta; i++) f.print_char(c)!; return max(0, delta); } @@ -191,7 +191,7 @@ fn char* fmt_u(uint128 x, char* s) fn usz? Formatter.out_chars(&self, char[] s) { - foreach (c : s) self.out(c)!; + foreach (c : s) self.print_char(c)!; return s.len; } @@ -203,12 +203,12 @@ enum FloatFormatting HEX } -fn usz? Formatter.etoa(&self, double y) => self.floatformat(EXPONENTIAL, y); -fn usz? Formatter.ftoa(&self, double y) => self.floatformat(FLOAT, y); -fn usz? Formatter.gtoa(&self, double y) => self.floatformat(ADAPTIVE, y); -fn usz? Formatter.atoa(&self, double y) => self.floatformat(HEX, y); +fn usz? formatter_etoa(Formatter* self, double y) => formatter_floatformat(self, EXPONENTIAL, y); +fn usz? formatter_ftoa(Formatter* self, double y) => formatter_floatformat(self, FLOAT, y); +fn usz? formatter_gtoa(Formatter* self, double y) => formatter_floatformat(self, ADAPTIVE, y); +fn usz? formatter_atoa(Formatter* self, double y) => formatter_floatformat(self, HEX, y); -fn usz? Formatter.floatformat_hex(&self, double y, bool is_neg, isz pl, isz p) @private @inline +fn usz? formatter_floatformat_hex(Formatter* self, double y, bool is_neg, isz pl, isz p) @private @inline { double round = 8.0; // 0x / 0X @@ -261,18 +261,18 @@ fn usz? Formatter.floatformat_hex(&self, double y, bool is_neg, isz pl, isz p) @ usz l = (usz)(p && outlen - 2 < p ? p + 2 + explen : outlen + explen); - if (!self.flags.left && !self.flags.zeropad) len += self.pad(' ', self.width, pl + l)!; - if (is_neg || self.flags.plus) len += self.out(is_neg ? '-' : '+')!; + if (!self.flags.left && !self.flags.zeropad) len += formatter_pad(self, ' ', self.width, pl + l)!; + if (is_neg || self.flags.plus) len += self.print_char(is_neg ? '-' : '+')!; len += self.out_chars(self.flags.uppercase ? "0X" : "0x")!; - if (self.flags.zeropad) len += self.pad('0', self.width, pl + l)!; + if (self.flags.zeropad) len += formatter_pad(self, '0', self.width, pl + l)!; len += self.out_chars(buf[:outlen])!; - len += self.pad('0', (isz)l - outlen - explen, 0)!; + len += formatter_pad(self, '0', (isz)l - outlen - explen, 0)!; len += self.out_chars(estr[:explen])!; - if (self.flags.left) len += self.pad(' ', self.width, pl + (isz)l)!; + if (self.flags.left) len += formatter_pad(self, ' ', self.width, pl + (isz)l)!; return len; } -fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @private +fn usz? formatter_floatformat(Formatter* self, FloatFormatting formatting, double y) @private { // This code is heavily based on musl's printf code const BUF_SIZE = (math::DOUBLE_MANT_DIG + 28) / 29 + 1 @@ -290,17 +290,17 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv { usz len; // Add padding - if (!self.flags.left) len += self.pad(' ', self.width, 3 + pl)!; + if (!self.flags.left) len += formatter_pad(self, ' ', self.width, 3 + pl)!; String s = self.flags.uppercase ? "INF" : "inf"; if (math::is_nan(y)) s = self.flags.uppercase ? "NAN" : "nan"; - if (pl) len += self.out(is_neg ? '-' : '+')!; + if (pl) len += self.print_char(is_neg ? '-' : '+')!; len += self.out_chars(s)!; - if (self.flags.left) len += self.pad(' ', self.width, 3 + pl)!; + if (self.flags.left) len += formatter_pad(self, ' ', self.width, 3 + pl)!; return len; } isz p = self.flags.precision ? self.prec : -1; - if (formatting == HEX) return self.floatformat_hex(y, is_neg, pl, p); + if (formatting == HEX) return formatter_floatformat_hex(self, y, is_neg, pl, p); // Rescale int e2; @@ -483,9 +483,9 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv } if (l > int.max - pl) return INTERNAL_BUFFER_EXCEEDED~; usz len; - if (!self.flags.left && !self.flags.zeropad) len += self.pad(' ', self.width, pl + l)!; - if (is_neg || self.flags.plus) len += self.out(is_neg ? '-' : '+')!; - if (self.flags.zeropad) len += self.pad('0', self.width, pl + l)!; + if (!self.flags.left && !self.flags.zeropad) len += formatter_pad(self, ' ', self.width, pl + l)!; + if (is_neg || self.flags.plus) len += self.print_char(is_neg ? '-' : '+')!; + if (self.flags.zeropad) len += formatter_pad(self, '0', self.width, pl + l)!; char[9] buf_array; char* buf = &buf_array[0]; @@ -506,14 +506,14 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv } len += self.out_chars(s[:buf + 9 - s])!; } - if (p || self.flags.hash) len += self.out('.')!; + if (p || self.flags.hash) len += self.print_char('.')!; for (; d < z && p > 0; d++, p -= 9) { char* s = fmt_u(*d, buf + 9); while (s > buf) *--s = '0'; len += self.out_chars(s[:math::min((isz)9, p)])!; } - len += self.pad('0', p + 9, 9)!; + len += formatter_pad(self, '0', p + 9, 9)!; } else { @@ -528,21 +528,42 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv } else { - len += self.out(s++[0])!; - if (p > 0 || self.flags.hash) len += self.out('.')!; + len += self.print_char(s++[0])!; + if (p > 0 || self.flags.hash) len += self.print_char('.')!; } len += self.out_chars(s[:math::min(buf + 9 - s, p)])!; p -= buf + 9 - s; } - len += self.pad('0', p + 18, 18)!; + len += formatter_pad(self, '0', p + 18, 18)!; len += self.out_chars(estr[:ebuf - estr])!; } - if (self.flags.left) len += self.pad(' ', self.width, pl + l)!; + if (self.flags.left) len += formatter_pad(self, ' ', self.width, pl + l)!; return len; } + +fn usz? formatter_out_str_pad(Formatter* self, any arg) @private @inline +{ + usz total; + if (self.width && !self.flags.left) + { + OutputFn out_fn = self.out_fn; + self.out_fn = (OutputFn)&out_null_fn; + usz len = formatter_out_str(self, arg)!; + self.out_fn = out_fn; + total += formatter_pad(self, ' ', self.width, (isz)len)!; + } + usz len = formatter_out_str(self, arg)!; + total += len; + if (self.flags.left) + { + total += formatter_pad(self, ' ', self.width, (isz)len)!; + } + return total; +} + const char[201] DIGIT_PAIRS @private = "00102030405060708090" "01112131415161718191" @@ -555,18 +576,18 @@ const char[201] DIGIT_PAIRS @private = "08182838485868788898" "09192939495969798999"; -fn usz? Formatter.ntoa(&self, uint128 value, bool negative, uint base) @private +fn usz? formatter_ntoa(Formatter* f, uint128 value, bool negative, uint base) @private { char[PRINTF_NTOA_BUFFER_SIZE] buf @noinit; usz len; // no hash for 0 values - if (!value) self.flags.hash = false; + if (!value) f.flags.hash = false; // write if precision != 0 or value is != 0 - if (!self.flags.precision || value) + if (!f.flags.precision || value) { - char past_10 = (self.flags.uppercase ? 'A' : 'a') - 10; + char past_10 = (f.flags.uppercase ? 'A' : 'a') - 10; switch (base) { case 2: @@ -612,27 +633,26 @@ fn usz? Formatter.ntoa(&self, uint128 value, bool negative, uint base) @private if (len >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED~; buf[len++] = '0' + (char)value & 0x7; value >>= 3; - } - while (value); + } while (value); default: unreachable(); } } - return self.ntoa_format((String)buf[:PRINTF_NTOA_BUFFER_SIZE], len, negative, base); + return formatter_ntoa_format(f, (String)buf[:PRINTF_NTOA_BUFFER_SIZE], len, negative, base); } -fn usz? Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint base) @private +fn usz? formatter_ntoa_format(Formatter* f, String buf, usz len, bool negative, uint base) @private { // pad leading zeros - if (!self.flags.left) + if (!f.flags.left) { - if (self.width && self.flags.zeropad && (negative || self.flags.plus || self.flags.space)) self.width--; - while (len < self.prec) + if (f.width && f.flags.zeropad && (negative || f.flags.plus || f.flags.space)) f.width--; + while (len < f.prec) { if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~; buf[len++] = '0'; } - while (self.flags.zeropad && len < self.width) + while (f.flags.zeropad && len < f.width) { if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~; buf[len++] = '0'; @@ -640,9 +660,9 @@ fn usz? Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint ba } // handle hash - if (self.flags.hash && base != 10) + if (f.flags.hash && base != 10) { - if (!self.flags.precision && len && len == self.prec && len == self.width) + if (!f.flags.precision && len && len == f.prec && len == f.width) { len--; if (len) len--; @@ -653,11 +673,11 @@ fn usz? Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint ba switch (base) { case 16: - buf[len++] = self.flags.uppercase ? 'X' : 'x'; + buf[len++] = f.flags.uppercase ? 'X' : 'x'; case 8: - buf[len++] = self.flags.uppercase ? 'O' : 'o'; + buf[len++] = f.flags.uppercase ? 'O' : 'o'; case 2: - buf[len++] = self.flags.uppercase ? 'B' : 'b'; + buf[len++] = f.flags.uppercase ? 'B' : 'b'; default: unreachable(); } @@ -670,35 +690,35 @@ fn usz? Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint ba case negative: if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~; buf[len++] = '-'; - case self.flags.plus: + case f.flags.plus: if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~; buf[len++] = '+'; - case self.flags.space: + case f.flags.space: if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~; buf[len++] = ' '; } - if (len) self.out_reverse(buf[:len])!; + if (len) formatter_out_reverse(f, buf[:len])!; return len; } -fn usz? Formatter.ntoa_any(&self, any arg, uint base) @private +fn usz? formatter_ntoa_any(Formatter* f, any arg, uint base) @private { bool is_neg; - return self.ntoa(int_from_any(arg, &is_neg)!!, is_neg, base) @inline; + return formatter_ntoa(f, int_from_any(arg, &is_neg)!!, is_neg, base) @inline; } -fn usz? Formatter.out_char(&self, any arg) @private +fn usz? formatter_out_char(Formatter* f, any arg) @private { if (!arg.type.kindof.is_int()) { - return self.out_substr(""); + return formatter_out_substr(f, ""); } usz len = 1; // pre padding - if (!self.flags.left) + if (!f.flags.left) { - len += self.pad(' ', self.width, len)!; + len += formatter_pad(f, ' ', f.width, len)!; } // char output @@ -706,42 +726,42 @@ fn usz? Formatter.out_char(&self, any arg) @private switch (true) { case c < 0x7f: - self.out((char)c)!; + f.print_char((char)c)!; case c < 0x7ff: - self.out((char)(0xC0 | c >> 6))!; - self.out((char)(0x80 | (c & 0x3F)))!; + f.print_char((char)(0xC0 | c >> 6))!; + f.print_char((char)(0x80 | (c & 0x3F)))!; case c < 0xffff: - self.out((char)(0xE0 | c >> 12))!; - self.out((char)(0x80 | (c >> 6 & 0x3F)))!; - self.out((char)(0x80 | (c & 0x3F)))!; + f.print_char((char)(0xE0 | c >> 12))!; + f.print_char((char)(0x80 | (c >> 6 & 0x3F)))!; + f.print_char((char)(0x80 | (c & 0x3F)))!; default: - self.out((char)(0xF0 | c >> 18))!; - self.out((char)(0x80 | (c >> 12 & 0x3F)))!; - self.out((char)(0x80 | (c >> 6 & 0x3F)))!; - self.out((char)(0x80 | (c & 0x3F)))!; + f.print_char((char)(0xF0 | c >> 18))!; + f.print_char((char)(0x80 | (c >> 12 & 0x3F)))!; + f.print_char((char)(0x80 | (c >> 6 & 0x3F)))!; + f.print_char((char)(0x80 | (c & 0x3F)))!; } - if (self.flags.left) + if (f.flags.left) { - len += self.pad(' ', self.width, len)!; + len += formatter_pad(f, ' ', f.width, len)!; } return len; } -fn usz? Formatter.out_reverse(&self, char[] buf) @private +fn usz? formatter_out_reverse(Formatter* f, char[] buf) @private { usz n; usz len = buf.len; // pad spaces up to given width - if (!self.flags.zeropad && !self.flags.left) + if (!f.flags.zeropad && !f.flags.left) { - n += self.pad(' ', self.width, len)!; + n += formatter_pad(f, ' ', f.width, len)!; } // reverse string - while (len) n += self.out(buf[--len])!; + while (len) n += f.print_char(buf[--len])!; // append pad spaces up to given width - n += self.adjust(n)!; + n += formatter_adjust(f, n)!; return n; } @@ -761,3 +781,197 @@ fn int? printf_parse_format_field( uint? intval = types::any_to_int(val, int); return intval ?? BAD_FORMAT~; } + +fn usz? formatter_out_hex_buffer(Formatter* self, any arg) @private @inline +{ + char[] out @noinit; + switch (arg.type) + { + case char[]: + case ichar[]: + out = *(char[]*)arg; + default: + if (arg.type.kindof == ARRAY && (arg.type.inner == char.typeid || arg.type.inner == ichar.typeid)) + { + out = ((char*)arg.ptr)[:arg.type.sizeof]; + break; + } + if (arg.type.kindof == POINTER) + { + // Maybe there is a more idiomatic way here + out = ((*(char**)arg.ptr))[:arg.type.inner.sizeof]; + break; + } + return formatter_out_substr(self, ""); + } + usz len = out.len * 2; + usz total; + if (self.flags.left) + { + total += print_hex_chars(self, out, self.flags.uppercase)!; + total += formatter_pad(self, ' ', self.width, (isz)total)!; + } + else + { + if (self.width) total += formatter_pad(self, ' ', self.width, (isz)len)!; + total += print_hex_chars(self, out, self.flags.uppercase)!; + } + return total; +} + + +fn usz? formatter_out_unknown(Formatter* self, String category, any arg) @private +{ + return formatter_out_substr(self, "<") + + formatter_out_substr(self, category) + + formatter_out_substr(self, " type:") + + formatter_ntoa(self, (iptr)arg.type, false, 16) + + formatter_out_substr(self, ", addr:") + + formatter_ntoa(self, (iptr)arg.ptr, false, 16) + + formatter_out_substr(self, ">"); +} + +fn usz? formatter_out_collection(Formatter* self, any arg, String open, String close) @private +{ + typeid inner = arg.type.inner; + if (inner == void.typeid) inner = char.typeid; + usz size = inner.sizeof; + + usz alen; + void* data_ptr; + if (arg.type.kindof == SLICE) + { + String* temp = arg.ptr; + data_ptr = temp.ptr; + alen = temp.len; + } + else + { + data_ptr = arg.ptr; + alen = arg.type.len; + } + + PrintFlags flags = self.flags; + uint width = self.width; + defer + { + self.flags = flags; + self.width = width; + } + self.flags = {}; + self.width = 0; + + usz len = formatter_out_substr(self, open)!; + for (usz i = 0; i < alen; i++) + { + if (i != 0) len += formatter_out_substr(self, ", ")!; + len += formatter_out_str(self, any_make(data_ptr, inner))!; + data_ptr += size; + } + len += formatter_out_substr(self, close)!; + return len; +} + +fn usz? formatter_out_str(Formatter* self, any arg) @private +{ + switch (arg.type.kindof) + { + case VOID: + return formatter_out_substr(self, "void"); + case FAULT: + fault f = *(fault*)arg.ptr; + return formatter_out_substr(self, f ? f.nameof : "(empty-fault)"); + case INTERFACE: + any a = *(any*)arg; + return a ? formatter_out_str(self, a) : formatter_out_substr(self, "(empty-interface)"); + case ANY: + any a = *(any*)arg; + return a ? formatter_out_str(self, a) : formatter_out_substr(self, "(empty-any)"); + case OPTIONAL: + unreachable(); + case SIGNED_INT: + case UNSIGNED_INT: + case FLOAT: + case FUNC: + case POINTER: + PrintFlags flags = self.flags; + uint width = self.width; + defer + { + self.flags = flags; + self.width = width; + } + self.flags = {}; + self.width = 0; + switch (arg.type.kindof) + { + case SIGNED_INT: + case UNSIGNED_INT: + return formatter_ntoa_any(self, arg, 10) ?? formatter_out_substr(self, ""); + case FLOAT: + return formatter_ftoa(self, float_from_any(arg)) ?? formatter_out_substr(self, "ERR"); + case FUNC: + case POINTER: + if (arg.type.kindof == POINTER && arg.type.inner != void.typeid) + { + void** pointer = arg.ptr; + any deref = any_make(*pointer, arg.type.inner); + usz? n = self.print_with_function((Printable)deref); + if (try n) return n; + if (@catch(n) != NOT_FOUND) n!; + } + return formatter_out_substr(self, "0x")! + formatter_ntoa_any(self, arg, 16); + default: + unreachable(); + } + case BOOL: + return formatter_out_substr(self, *(bool*)arg.ptr ? "true" : "false"); + default: + } + usz? n = self.print_with_function((Printable)arg); + if (try n) return n; + if (@catch(n) != NOT_FOUND) n!; + switch (arg.type.kindof) + { + case TYPEID: + return formatter_out_substr(self, "typeid[")! + formatter_ntoa(self, (iptr)*(typeid*)arg, false, 16)! + formatter_out_substr(self, "]")!; + case ENUM: + usz i = types::any_to_enum_ordinal(arg, usz)!!; + assert(i < arg.type.names.len, "Illegal enum value found, numerical value was %d.", i); + return formatter_out_substr(self, arg.type.names[i]); + case STRUCT: + return formatter_out_unknown(self, "struct", arg); + case UNION: + return formatter_out_unknown(self, "union", arg); + case BITSTRUCT: + return formatter_out_unknown(self, "bitstruct", arg); + case CONST_ENUM: + case DISTINCT: + if (arg.type == String.typeid) + { + return formatter_out_substr(self, *(String*)arg); + } + if (arg.type == ZString.typeid) + { + return formatter_out_substr(self, *(ZString*)arg ? ((ZString*)arg).str_view() : "(null)"); + } + if (arg.type == DString.typeid) + { + return formatter_out_substr(self, *(DString*)arg ? ((DString*)arg).str_view() : "(null)"); + } + return formatter_out_str(self, arg.as_inner()); + case ARRAY: + return formatter_out_collection(self, arg, "[", "]"); + case VECTOR: + return formatter_out_collection(self, arg, "[<", ">]"); + case SLICE: + return formatter_out_collection(self, arg, "[", "]"); + case ANY: + case INTERFACE: + unreachable("Already handled"); + default: + } + return formatter_out_substr(self, "Invalid type"); +} + + diff --git a/lib/std/io/io.c3 b/lib/std/io/io.c3 index a3b19416f..e09ab8d6c 100644 --- a/lib/std/io/io.c3 +++ b/lib/std/io/io.c3 @@ -366,7 +366,7 @@ fn usz? printfn(String format, args...) @format(0) @maydiscard PutcharBuffer buff; formatter.init(&out_putchar_buffer_fn, &buff); usz? len = formatter.vprintf(format, args); - formatter.out('\n')!; + formatter.print_char('\n')!; write_putchar_buffer(&buff, true)!; return len + 1; } diff --git a/lib/std/io/stream/buffer.c3 b/lib/std/io/stream/buffer.c3 index 337ebcf41..792fb1c5a 100644 --- a/lib/std/io/stream/buffer.c3 +++ b/lib/std/io/stream/buffer.c3 @@ -38,7 +38,7 @@ fn usz? ReadBuffer.read(&self, char[] bytes) @dynamic // Read directly into the input buffer. return self.wrapped_stream.read(bytes)!; } - self.refill()!; + readbuffer_refill(self)!; } usz n = min(self.write_idx - self.read_idx, bytes.len); bytes[:n] = self.bytes[self.read_idx:n]; @@ -48,14 +48,14 @@ fn usz? ReadBuffer.read(&self, char[] bytes) @dynamic fn char? ReadBuffer.read_byte(&self) @dynamic { - if (self.read_idx == self.write_idx) self.refill()!; + if (self.read_idx == self.write_idx) readbuffer_refill(self)!; if (self.read_idx == self.write_idx) return io::EOF~; char c = self.bytes[self.read_idx]; self.read_idx++; return c; } -fn void? ReadBuffer.refill(&self) @local @inline +fn void? readbuffer_refill(ReadBuffer* self) @local @inline { self.read_idx = 0; self.write_idx = self.wrapped_stream.read(self.bytes)!; @@ -92,7 +92,7 @@ fn void? WriteBuffer.close(&self) @dynamic fn void? WriteBuffer.flush(&self) @dynamic { - self.write_pending()!; + write_buffer_write_pending(self)!; if (&self.wrapped_stream.flush) self.wrapped_stream.flush()!; } @@ -106,7 +106,7 @@ fn usz? WriteBuffer.write(&self, char[] bytes) @dynamic self.index += bytes.len; return bytes.len; } - self.write_pending()!; + write_buffer_write_pending(self)!; if (bytes.len >= self.bytes.len) { // Write directly to the stream. @@ -123,13 +123,13 @@ fn void? WriteBuffer.write_byte(&self, char c) @dynamic usz n = self.bytes.len - self.index; if (n == 0) { - self.write_pending()!; + write_buffer_write_pending(self)!; } self.bytes[self.index] = c; self.index += 1; } -fn void? WriteBuffer.write_pending(&self) @local +fn void? write_buffer_write_pending(WriteBuffer* self) @local { self.index -= self.wrapped_stream.write(self.bytes[:self.index])!; if (self.index != 0) return INCOMPLETE_WRITE~; diff --git a/lib/std/math/bigint.c3 b/lib/std/math/bigint.c3 index b0af70dfd..686049a63 100644 --- a/lib/std/math/bigint.c3 +++ b/lib/std/math/bigint.c3 @@ -37,7 +37,7 @@ fn BigInt* BigInt.init(&self, int128 value) assert(value < 0 || tmp == 0 || !self.is_negative()); assert(value >= 0 || tmp == -1 || self.is_negative()); self.len = len; - self.reduce_len(); + reduce_len(self); return self; } @@ -153,15 +153,11 @@ fn void BigInt.add_this(&self, BigInt other) @operator(+=) self.data[self.len++] = (uint)carry; } - self.reduce_len(); + reduce_len(self); assert(sign != sign_arg || sign == self.is_negative(), "Overflow in addition"); } -fn void BigInt.reduce_len(&self) @private -{ - self.len = max(find_length(&self.data, self.len), 1); -} macro uint find_length(uint* data, uint length) { @@ -226,7 +222,7 @@ fn void BigInt.mult_this(&self, BigInt bi2) @operator(*=) res.len = min(self.len + bi2.len, (uint)MAX_LEN); - res.reduce_len(); + reduce_len(&res); // overflow check (result is -ve) assert(!res.is_negative(), "Multiplication overflow"); @@ -265,7 +261,7 @@ fn void BigInt.negate(&self) assert(self.is_negative() != was_negative, "Overflow in negation"); self.len = MAX_LEN; - self.reduce_len(); + reduce_len(self); } macro bool BigInt.is_zero(&self) => self.len == 1 && self.data[0] == 0; @@ -301,7 +297,7 @@ fn BigInt* BigInt.sub_this(&self, BigInt other) @operator(-=) self.len = MAX_LEN; } - self.reduce_len(); + reduce_len(self); // overflow check @@ -311,7 +307,7 @@ fn BigInt* BigInt.sub_this(&self, BigInt other) @operator(-=) fn int BigInt.bitcount(&self) { - self.reduce_len(); + reduce_len(self); uint val = self.data[self.len - 1]; uint mask = 0x80000000; int bits = 32; @@ -364,11 +360,11 @@ fn void BigInt.div_this(&self, BigInt other) @operator(/=) if (other.len == 1) { - self.single_byte_divide(&other, "ient, &remainder); + single_byte_divide(self, &other, "ient, &remainder); } else { - self.multi_byte_divide(&other, "ient, &remainder); + multi_byte_divide(self, &other, "ient, &remainder); } if (negate_answer) { @@ -407,11 +403,11 @@ fn void BigInt.mod_this(&self, BigInt bi2) @operator(%=) if (bi2.len == 1) { - self.single_byte_divide(&bi2, "ient, &remainder); + single_byte_divide(self, &bi2, "ient, &remainder); } else { - self.multi_byte_divide(&bi2, "ient, &remainder); + multi_byte_divide(self, &bi2, "ient, &remainder); } if (negate_answer) { @@ -425,7 +421,7 @@ fn void BigInt.bit_negate_this(&self) foreach (&r : self.data) *r = ~*r; self.len = MAX_LEN; - self.reduce_len(); + reduce_len(self); } fn BigInt BigInt.bit_negate(self) @operator(~) @@ -523,7 +519,7 @@ fn usz? BigInt.to_format(&self, Formatter* format) @dynamic usz len; if (negative) { - format.out('-')!; + format.print_char('-')!; len++; a.negate(); } @@ -580,7 +576,7 @@ fn String BigInt.to_string_with_radix(&self, int radix, Allocator allocator) while (!a.is_zero()) { - a.single_byte_divide(&big_radix, "ient, &remainder); + single_byte_divide(&a, &big_radix, "ient, &remainder); if (remainder.data[0] < 10) { @@ -740,7 +736,7 @@ fn BigInt barrett_reduction(BigInt x, BigInt n, BigInt constant) } r2.len = k_plus_one; - r2.reduce_len(); + reduce_len(&r2); r1.sub_this(r2); if (r1.is_negative()) @@ -816,7 +812,7 @@ fn void BigInt.bit_and_this(&self, BigInt bi2) } self.len = MAX_LEN; - self.reduce_len(); + reduce_len(self); } fn BigInt BigInt.bit_or(self, BigInt bi2) @operator(|) @@ -834,7 +830,7 @@ fn void BigInt.bit_or_this(&self, BigInt bi2) } self.len = MAX_LEN; - self.reduce_len(); + reduce_len(self); } fn BigInt BigInt.bit_xor(self, BigInt bi2) @operator(^) @@ -852,7 +848,7 @@ fn void BigInt.bit_xor_this(&self, BigInt bi2) } self.len = MAX_LEN; - self.reduce_len(); + reduce_len(self); } fn void BigInt.shl_this(&self, int shift) @operator(<<=) @@ -928,13 +924,18 @@ fn void BigInt.randomize_bits(&self, Random random, int bits) module std::math::bigint @private; +fn void reduce_len(BigInt* self) @private +{ + self.len = max(find_length(&self.data, self.len), 1); +} + <* @param [&inout] quotient @param [&in] bi2 @param [&inout] remainder *> -fn void BigInt.single_byte_divide(&self, BigInt* bi2, BigInt* quotient, BigInt* remainder) +fn void single_byte_divide(BigInt* self, BigInt* bi2, BigInt* quotient, BigInt* remainder) @private { uint[MAX_LEN] result; int result_pos = 0; @@ -977,8 +978,8 @@ fn void BigInt.single_byte_divide(&self, BigInt* bi2, BigInt* quotient, BigInt* } quotient.data[j..] = 0; - quotient.reduce_len(); - remainder.reduce_len(); + reduce_len(quotient); + reduce_len(remainder); } <* @@ -986,7 +987,7 @@ fn void BigInt.single_byte_divide(&self, BigInt* bi2, BigInt* quotient, BigInt* @param [&in] other @param [&inout] remainder *> -fn void BigInt.multi_byte_divide(&self, BigInt* other, BigInt* quotient, BigInt* remainder) +fn void multi_byte_divide(BigInt* self, BigInt* other, BigInt* quotient, BigInt* remainder) { uint[MAX_LEN] result; uint[MAX_LEN] r; @@ -1081,7 +1082,7 @@ fn void BigInt.multi_byte_divide(&self, BigInt* other, BigInt* quotient, BigInt* quotient.data[y] = 0; } - quotient.reduce_len(); + reduce_len(quotient); remainder.len = shift_right(&r, remainder_len, shift); diff --git a/lib/std/threads/os/thread_win32.c3 b/lib/std/threads/os/thread_win32.c3 index 7d48576d0..2f3d27094 100644 --- a/lib/std/threads/os/thread_win32.c3 +++ b/lib/std/threads/os/thread_win32.c3 @@ -142,7 +142,7 @@ fn void NativeTimedMutex.destroy(&mtx) *mtx = {}; } -fn void? NativeTimedMutex.wait_cond_var(&mtx, uint ms) @local +fn void? _wait_cond_var(NativeTimedMutex *mtx, uint ms) @local { if (!win32::sleepConditionVariableSRW(&mtx.cond_var, &mtx.srw_lock, ms, 0)) { @@ -169,7 +169,7 @@ fn void NativeTimedMutex.lock(&mtx) while (mtx.locks) { - mtx.wait_cond_var(win32::INFINITE)!!; + _wait_cond_var(mtx, win32::INFINITE)!!; } mtx.locks = 1; mtx.owner_thread = current_thread; @@ -206,7 +206,7 @@ fn void? NativeTimedMutex.lock_timeout(&mtx, ulong ms) { ulong remaining_ms = remaining.to_ms(); if (remaining_ms > uint.max) remaining_ms = uint.max; - mtx.wait_cond_var((uint)remaining_ms)!; + _wait_cond_var(mtx, (uint)remaining_ms)!; if (!mtx.locks) { // Got the lock diff --git a/releasenotes.md b/releasenotes.md index 5ddf490c2..cc8bc1d1e 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -55,6 +55,7 @@ - Adding the incorrect sized vector to a pointer vector would cause a crash. - Member access on a struct returned by the assignment expression, cause crash #2947 - Trying to slice an indexable type leads to misleading error message #2958 +- Warn on use of visibility modifiers on methods. #2962 ## 0.7.9 Change list diff --git a/src/build/build.h b/src/build/build.h index d5034895b..4ae163fbc 100644 --- a/src/build/build.h +++ b/src/build/build.h @@ -97,6 +97,7 @@ typedef struct WarningLevel deprecation; WarningLevel methods_not_resolved; WarningLevel dead_code; + WarningLevel method_visibility; } Warnings; typedef enum diff --git a/src/build/build_options.c b/src/build/build_options.c index 523c5ee18..987aa08fa 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -142,6 +142,7 @@ static void usage(bool full) print_opt("--use-old-compact-eq", "Enable the old ability to use '@compact' to make a struct comparable."); print_opt("--print-large-functions", "Print functions with large compile size."); print_opt("--warn-deadcode=", "Print warning on dead-code: yes, no, error."); + print_opt("--warn-methodvisibility=", "Print warning when methods have ignored visibility attributes."); print_opt("--warn-methodsnotresolved=", "Print warning on methods not resolved when accessed: yes, no, error."); print_opt("--warn-deprecation=", "Print warning when using deprecated code and constructs: yes, no, error."); } @@ -906,6 +907,11 @@ static void parse_option(BuildOptions *options) options->warnings.dead_code = parse_opt_select(WarningLevel, argopt, warnings); return; } + if ((argopt = match_argopt("warn-methodvisibility"))) + { + options->warnings.method_visibility = parse_opt_select(WarningLevel, argopt, warnings); + return; + } if ((argopt = match_argopt("warn-methodsnotresolved"))) { options->warnings.methods_not_resolved = parse_opt_select(WarningLevel, argopt, warnings); diff --git a/src/build/builder.c b/src/build/builder.c index d83e8651e..691ff0a0c 100644 --- a/src/build/builder.c +++ b/src/build/builder.c @@ -536,6 +536,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions * update_warning_if_not_set(&target->warnings.deprecation, WARNING_SILENT); update_warning_if_not_set(&target->warnings.methods_not_resolved, WARNING_WARN); update_warning_if_not_set(&target->warnings.dead_code, WARNING_SILENT); + update_warning_if_not_set(&target->warnings.method_visibility, WARNING_WARN); break; case VALIDATION_NOT_SET: target->validation_level = VALIDATION_STRICT; @@ -544,16 +545,19 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions * update_warning_if_not_set(&target->warnings.methods_not_resolved, WARNING_WARN); update_warning_if_not_set(&target->warnings.deprecation, WARNING_WARN); update_warning_if_not_set(&target->warnings.dead_code, WARNING_WARN); + update_warning_if_not_set(&target->warnings.method_visibility, WARNING_WARN); break; case VALIDATION_OBNOXIOUS: update_warning_if_not_set(&target->warnings.methods_not_resolved, WARNING_ERROR); update_warning_if_not_set(&target->warnings.deprecation, WARNING_ERROR); update_warning_if_not_set(&target->warnings.dead_code, WARNING_ERROR); + update_warning_if_not_set(&target->warnings.method_visibility, WARNING_ERROR); break; } update_warning(&target->warnings.deprecation, options->warnings.deprecation); update_warning(&target->warnings.dead_code, options->warnings.dead_code); update_warning(&target->warnings.methods_not_resolved, options->warnings.methods_not_resolved); + update_warning(&target->warnings.method_visibility, options->warnings.method_visibility); target->print_linking = options->print_linking || options->verbosity_level > 1; diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index 9e5105433..ac3fe133b 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -414,7 +414,7 @@ static Expr *parse_lambda(ParseContext *c, Expr *left, SourceSpan lhs_span UNUSE sig->params = decls; sig->rtype = return_type ? type_infoid(return_type) : 0; sig->variadic = variadic; - if (!parse_attributes(c, &func->attributes, NULL, NULL, NULL)) return poisoned_expr; + if (!parse_attributes(c, &func->attributes, NULL, NULL, NULL, "on lambda declarations")) return poisoned_expr; RANGE_EXTEND_PREV(func); if (tok_is(c, TOKEN_IMPLIES)) { diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index daa45fcd4..f6863640e 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -310,7 +310,7 @@ bool parse_module(ParseContext *c, ContractDescription *contracts) ASSIGN_DECL_OR_RET(Decl *generic_decl, parse_generic_decl(c), false); - if (!parse_attributes(c, &attrs, &visibility, NULL, &is_cond)) return false; + if (!parse_attributes(c, &attrs, &visibility, NULL, &is_cond, NULL)) return false; if (generic_decl_old) { SEMA_DEPRECATED(generic_decl_old, "Module-based generics is deprecated, use `<...>` instead."); @@ -931,7 +931,7 @@ Decl *parse_local_decl_after_type(ParseContext *c, TypeInfo *type) advance(c); bool is_cond; - if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond, "on local variables")) return poisoned_decl; decl->is_cond = is_cond; if (tok_is(c, TOKEN_EQ)) { @@ -1012,7 +1012,7 @@ Decl *parse_const_declaration(ParseContext *c, bool is_global, bool is_extern) else { bool is_cond; - if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond, "on local declarations")) return poisoned_decl; decl->is_cond = is_cond; } @@ -1043,7 +1043,7 @@ Decl *parse_var_decl(ParseContext *c) case TOKEN_IDENT: decl = decl_new_var_current(c, NULL, VARDECL_LOCAL); advance(c); - if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond, "on local declarations")) return poisoned_decl; decl->is_cond = is_cond; if (!tok_is(c, TOKEN_EQ)) { @@ -1058,7 +1058,7 @@ Decl *parse_var_decl(ParseContext *c) decl = decl_new_var_current(c, NULL, c->tok == TOKEN_CT_IDENT ? VARDECL_LOCAL_CT : VARDECL_LOCAL_CT_TYPE); advance(c); span = c->span; - if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond, "on local declarations")) return poisoned_decl; if (is_cond || decl->attributes) { print_error_at(span, "Attributes are not allowed on compile time variables."); @@ -1320,7 +1320,8 @@ static bool parse_attributes_for_global(ParseContext *c, Decl *decl) bool is_cond; bool can_be_generic = decl_may_be_generic(decl); ASSIGN_DECL_OR_RET(Decl *generics, parse_generic_decl(c), false); - if (!parse_attributes(c, &decl->attributes, &visibility, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond)) return false; + bool is_method = decl->decl_kind == DECL_FUNC && decl->func_decl.type_parent; + if (!parse_attributes(c, &decl->attributes, &visibility, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond, is_method ? "for method declarations" : NULL)) return false; if (generics) { if (!can_be_generic) @@ -1345,7 +1346,22 @@ static bool parse_attributes_for_global(ParseContext *c, Decl *decl) return true; } -static inline bool parse_attribute_list(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref, bool use_comma) +static inline bool warn_method_visibility(Attr *attr, const char *mod, const char *err) +{ + switch (compiler.build.warnings.method_visibility) + { + case WARNING_WARN: + sema_warning_at(attr->span, "'%s' modifiers are ignored %s.", mod, err); + return true; + case WARNING_ERROR: + print_error_at(attr->span, "'%s' modifiers are not allowed %s.", mod, err); + return false; + default: + return true; + } +} + +static inline bool parse_attribute_list(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref, bool use_comma, const char *reject_visibility) { Visibility visibility = -1; // NOLINT if (cond_ref) *cond_ref = false; @@ -1364,12 +1380,36 @@ static inline bool parse_attribute_list(ParseContext *c, Attr ***attributes_ref, switch (attr->attr_kind) { case ATTRIBUTE_PUBLIC: + if (reject_visibility && attributes_ref) + { + if (!warn_method_visibility(attr, "@public", reject_visibility)) return false; + } + else if (reject_visibility) + { + RETURN_PRINT_ERROR_AT(false, attr, "Visibility modifiers are not allowed %s.", reject_visibility); + } parsed_visibility = VISIBLE_PUBLIC; break; case ATTRIBUTE_PRIVATE: + if (reject_visibility && attributes_ref) + { + if (!warn_method_visibility(attr, "@private", reject_visibility)) return false; + } + else if (reject_visibility) + { + RETURN_PRINT_ERROR_AT(false, attr, "Visibility modifiers are not allowed %s.", reject_visibility); + } parsed_visibility = VISIBLE_PRIVATE; break; case ATTRIBUTE_LOCAL: + if (reject_visibility && attributes_ref) + { + if (!warn_method_visibility(attr, "@local", reject_visibility)) return false; + } + else if (reject_visibility) + { + RETURN_PRINT_ERROR_AT(false, attr, "Visibility modifiers are not allowed %s.", reject_visibility); + } parsed_visibility = VISIBLE_LOCAL; break; case ATTRIBUTE_BUILTIN: @@ -1458,9 +1498,9 @@ Decl *parse_generic_decl(ParseContext *c) * * @return true if parsing succeeded, false if recovery is needed */ -bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref) +bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref, const char *reject_visibility) { - return parse_attribute_list(c, attributes_ref, visibility_ref, builtin_ref, cond_ref, false); + return parse_attribute_list(c, attributes_ref, visibility_ref, builtin_ref, cond_ref, false, reject_visibility); } /** @@ -1594,7 +1634,7 @@ static inline bool parse_enum_param_decl(ParseContext *c, Decl*** parameters) if (token_is_some_ident(c->tok)) RETURN_PRINT_ERROR_HERE("Expected a name starting with a lower-case letter."); RETURN_PRINT_ERROR_HERE("Expected a member name here."); } - if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL)) return false; + if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL, "on parameter declarations")) return false; vec_add(*parameters, param); RANGE_EXTEND_PREV(param); return true; @@ -1847,7 +1887,7 @@ CHECK_ELLIPSIS: Decl *param = decl_new_var(name, span, type, param_kind); param->var.type_info = type ? type_infoid(type) : 0; param->var.self_addr = ref; - if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL)) return false; + if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL, "on parameters")) return false; if (!no_name) { if (try_consume(c, TOKEN_EQ)) @@ -1985,7 +2025,7 @@ static bool parse_struct_body(ParseContext *c, Decl *parent) else { bool is_cond; - if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond)) return false; + if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond, "on struct and union fields")) return false; member->is_cond = true; if (!parse_struct_body(c, member)) return decl_poison(parent); } @@ -2029,7 +2069,7 @@ static bool parse_struct_body(ParseContext *c, Decl *parent) } advance(c); bool is_cond; - if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond)) return false; + if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond, "on struct and union fields")) return false; member->is_cond = true; if (!try_consume(c, TOKEN_COMMA)) break; if (was_inline) @@ -2178,7 +2218,7 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) is_consecutive = true; } bool is_cond = false; - if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond)) return false; + if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond, "on bitstruct fields")) return false; member_decl->is_cond = is_cond; CONSUME_OR_RET(TOKEN_EOS, false); unsigned index = vec_size(decl->strukt.members); @@ -2199,7 +2239,7 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) member_decl->var.end = NULL; } bool is_cond = false; - if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond)) return false; + if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond, "on bitstruct fields")) return false; member_decl->is_cond = is_cond; CONSUME_EOS_OR_RET(false); if (is_consecutive) @@ -2396,7 +2436,7 @@ static inline Decl *parse_alias_type(ParseContext *c, ContractDescription *contr { return poisoned_decl; } - if (!parse_attributes(c, &decl_type->attributes, NULL, NULL, NULL)) return poisoned_decl; + if (!parse_attributes(c, &decl_type->attributes, NULL, NULL, NULL, "on the target of an alias (maybe you intended it *before* the '='?)")) return poisoned_decl; attach_deprecation_from_contract(c, contracts, decl_type); RANGE_EXTEND_PREV(decl_type); RANGE_EXTEND_PREV(decl); @@ -2584,7 +2624,7 @@ static inline Decl *parse_attrdef(ParseContext *c) bool is_cond; bool is_builtin = false; - if (!parse_attribute_list(c, &attributes, NULL, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond, true)) return poisoned_decl; + if (!parse_attribute_list(c, &attributes, NULL, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond, true, "cannot be aliased using 'attrdef'")) return poisoned_decl; decl->attr_decl.attrs = attributes; CONSUME_EOS_OR_RET(poisoned_decl); return decl; diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index 9418cb9a2..4a8170a57 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -64,7 +64,7 @@ Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool is_regular_f bool parse_attribute(ParseContext *c, Attr **attribute_ref, bool expect_eos); -bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref); +bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref, const char *reject_visibility); Decl *parse_generic_decl(ParseContext *c); bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 0ad8cd717..7769a20dd 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -2870,6 +2870,7 @@ static inline bool sema_compare_method_with_interface(SemaContext *context, Decl static inline bool sema_analyse_method(SemaContext *context, Decl *decl) { ASSERT_SPAN(decl, decl->decl_kind == DECL_FUNC); + // Check for @init, @finalizer, @test and @benchmark if (decl->func_decl.attr_init | decl->func_decl.attr_finalizer) { @@ -2884,6 +2885,7 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl) // Resolve the parent type. TypeInfo *parent_type = type_infoptr(decl->func_decl.type_parent); + ASSERT(parent_type->resolve_status == RESOLVE_DONE); Type *par_type = parent_type->type->canonical; diff --git a/test/test_suite/methods/access_private_method.c3 b/test/test_suite/methods/access_private_method.c3 index cc5c6f75b..1c6430092 100644 --- a/test/test_suite/methods/access_private_method.c3 +++ b/test/test_suite/methods/access_private_method.c3 @@ -1,9 +1,9 @@ alias NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data); -fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) @private {} +fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) {} struct TreeNode { int abc; NodeNotifyHandler notifyHandler; } struct TreeView { int abc; } -fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1) @private +fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1) { node.notifyHandler = &TreeView.nodeNotifyHandler; // This is the line } \ No newline at end of file diff --git a/test/test_suite/methods/extending_with_visibility.c3 b/test/test_suite/methods/extending_with_visibility.c3 deleted file mode 100644 index 64119422e..000000000 --- a/test/test_suite/methods/extending_with_visibility.c3 +++ /dev/null @@ -1,35 +0,0 @@ -module test; -import abc; - -struct Foo -{ - int x; -} - -fn int Foo.get1(Foo* f) @private => f.x; -fn int Foo.get2(Foo* f) => f.x; -fn int Foo.get3(Foo* f) @local => f.x; - -fn int Bar.get1(Bar* f) @private => f.x; -fn int Bar.get2(Bar* f) => f.x; -fn int Bar.get3(Bar* f) @local => f.x; - -fn int main() -{ - Foo x = { 1 }; - x.get1(); - x.get2(); - x.get3(); - Bar y = { 1 }; - y.get1(); - y.get2(); - y.get3(); - return 1; -} - -module abc; - -struct Bar -{ - int x; -} diff --git a/test/test_suite/methods/extending_with_visibility_fail.c3 b/test/test_suite/methods/extending_with_visibility_fail.c3 deleted file mode 100644 index 2e1104ee8..000000000 --- a/test/test_suite/methods/extending_with_visibility_fail.c3 +++ /dev/null @@ -1,37 +0,0 @@ -module test; -import abc; - -struct Foo -{ - int x; -} - -fn int Foo.get1(Foo* f) @private => f.x; -fn int Foo.get2(Foo* f) => f.x; -fn int Foo.get3(Foo* f) @local => f.x; - -fn int Bar.get1(Bar* f) @private => f.x; -fn int Bar.get2(Bar* f) => f.x; -fn int Bar.get3(Bar* f) @local => f.x; - -module abc; -import test; - -struct Bar -{ - int x; -} - -Foo x = { 1 }; -Bar y = { 1 }; - -fn int test() -{ - x.get1(); - x.get2(); - x.get3(); - y.get1(); - y.get2(); - y.get3(); - return 1; -} diff --git a/test/test_suite/methods/extending_with_visibility_fail_private.c3 b/test/test_suite/methods/extending_with_visibility_fail_private.c3 deleted file mode 100644 index 301ce5c61..000000000 --- a/test/test_suite/methods/extending_with_visibility_fail_private.c3 +++ /dev/null @@ -1,37 +0,0 @@ -module test; -import abc; - -struct Foo -{ - int x; -} - -fn int Foo.get1(Foo* f) @private => f.x; -fn int Foo.get2(Foo* f) => f.x; -fn int Foo.get3(Foo* f) @local => f.x; - -fn int Bar.get1(Bar* f) @private => f.x; -fn int Bar.get2(Bar* f) => f.x; -fn int Bar.get3(Bar* f) @local => f.x; - -module abc; -import test @public; - -struct Bar -{ - int x; -} - -Foo x = { 1 }; -Bar y = { 1 }; - -fn int test() -{ - x.get1(); - x.get2(); - x.get3(); - y.get1(); - y.get2(); - y.get3(); - return 1; -} diff --git a/test/test_suite/methods/method_from_var.c3 b/test/test_suite/methods/method_from_var.c3 index 4874c5d48..155181e7c 100644 --- a/test/test_suite/methods/method_from_var.c3 +++ b/test/test_suite/methods/method_from_var.c3 @@ -1,9 +1,9 @@ alias NodeNotifyHandler = fn void(TreeView* this, TreeNode* node, String prop, void* data); -fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) @private {} +fn void TreeView.nodeNotifyHandler(TreeView* this, TreeNode* node, String prop, void* data) {} struct TreeNode { int abc; NodeNotifyHandler notifyHandler; } struct TreeView { int abc; } -fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1) @private +fn void TreeView.addNodeInternal(TreeView* this, int nop, TreeNode* node, TreeNode* pnode = null, int pos = -1) { node.notifyHandler = &(this.nodeNotifyHandler); // #error: Taking the address of a method } \ No newline at end of file diff --git a/test/test_suite/switch/switch_in_defer_macro.c3t b/test/test_suite/switch/switch_in_defer_macro.c3t index 31ce3dde4..d82eb9ec0 100644 --- a/test/test_suite/switch/switch_in_defer_macro.c3t +++ b/test/test_suite/switch/switch_in_defer_macro.c3t @@ -143,7 +143,7 @@ fn Token? Lexer.expect(&self, fault err, Token... tokens) return err~; } -fn void? Lexer.skip_whitespace(&self) @private +fn void? Lexer.skip_whitespace(&self) { self.span = 0; while (true) @@ -166,7 +166,7 @@ fn void? Lexer.skip_whitespace(&self) @private } } -fn ulong? Lexer.parse_uint(&self) @private +fn ulong? Lexer.parse_uint(&self) { ulong x; char c = self.reader.read_byte()!; @@ -190,7 +190,7 @@ fn ulong? Lexer.parse_uint(&self) @private return self.parse_decimal()!; } -fn ulong? Lexer.parse_decimal(&self) @private +fn ulong? Lexer.parse_decimal(&self) { return @parse_uint(self, ulong; ulong x, char c, bool ok) { @@ -202,7 +202,7 @@ fn ulong? Lexer.parse_decimal(&self) @private }; } -fn ulong? Lexer.parse_hexadecimal(&self) @private +fn ulong? Lexer.parse_hexadecimal(&self) { return @parse_uint(self, ulong; ulong x, char c, bool ok) { @@ -219,7 +219,7 @@ fn ulong? Lexer.parse_hexadecimal(&self) @private }; } -fn ulong? Lexer.parse_binary(&self) @private +fn ulong? Lexer.parse_binary(&self) { return @parse_uint(self, ulong; ulong x, char c, bool ok) { @@ -231,7 +231,7 @@ fn ulong? Lexer.parse_binary(&self) @private }; } -fn ulong? Lexer.parse_octal(&self) @private +fn ulong? Lexer.parse_octal(&self) { return @parse_uint(self, ulong; ulong x, char c, bool ok) { @@ -275,7 +275,7 @@ macro @parse_uint(self, $Type; @body(x, c, ok)) @private return x; } -fn String? Lexer.parse_string(&self, char quote) @private +fn String? Lexer.parse_string(&self, char quote) { char c = self.read_char_for_string()!; if (c == quote) return ""; @@ -316,7 +316,7 @@ fn String? Lexer.parse_string(&self, char quote) @private } } -fn char? Lexer.parse_rune(&self) @private +fn char? Lexer.parse_rune(&self) { char x = self.reader.read_byte()!; char c = self.reader.read_byte()!; @@ -324,7 +324,7 @@ fn char? Lexer.parse_rune(&self) @private return x; } -macro char? Lexer.read_char_for_string(&self) @private +macro char? Lexer.read_char_for_string(&self) { char? c = self.reader.read_byte(); if (catch err = c) @@ -335,7 +335,7 @@ macro char? Lexer.read_char_for_string(&self) @private return c; } -fn Token? Lexer.parse_token(&self) @private +fn Token? Lexer.parse_token(&self) { usz n = self.reader.read(self.buf)!; defer self.unread(n); @@ -344,7 +344,7 @@ fn Token? Lexer.parse_token(&self) @private return tok; } -fn void? Lexer.parse_comment(&self, String end) @private +fn void? Lexer.parse_comment(&self, String end) { // Find the end token and accumulate the data in between. DString acc; @@ -367,7 +367,7 @@ fn void? Lexer.parse_comment(&self, String end) @private } } -macro Lexer.unread(self, n) @private +macro Lexer.unread(self, n) { switch { @@ -383,7 +383,7 @@ macro Lexer.unread(self, n) @private } } -fn String? Lexer.parse_ident(&self) @private +fn String? Lexer.parse_ident(&self) { DString str; str.init(self.allocator, 8); @@ -528,7 +528,7 @@ fn void? Trie.del(&self, char[] key) self.nodes[0].del(self, key, path)!; } -fn Value? TrieNode.get(&self, Trie *t, char[] key) @private +fn Value? TrieNode.get(&self, Trie *t, char[] key) { if (key.len == 0) return self.valid ? self.value : NOT_FOUND~; char c = key[0]; @@ -537,7 +537,7 @@ fn Value? TrieNode.get(&self, Trie *t, char[] key) @private return t.nodes[idx].get(t, key[1..]); } -fn Value? TrieNode.get_best(&self, Trie *t, char[] key, Index result) @private +fn Value? TrieNode.get_best(&self, Trie *t, char[] key, Index result) { if (key.len == 0) { @@ -556,7 +556,7 @@ fn Value? TrieNode.get_best(&self, Trie *t, char[] key, Index result) @private return next.get_best(t, key[1..], result); } -fn void? TrieNode.set(&self, Trie *t, char[] key, Value value) @private +fn void? TrieNode.set(&self, Trie *t, char[] key, Value value) { if (key.len == 0) { @@ -578,7 +578,7 @@ fn void? TrieNode.set(&self, Trie *t, char[] key, Value value) @private t.nodes[idx].set(t, key[1..], value)!; } -fn void? TrieNode.del(&self, Trie* t, char[] key, TriePath path) @private +fn void? TrieNode.del(&self, Trie* t, char[] key, TriePath path) { if (key.len > 0) { diff --git a/test/unit/regression/operator_overload.c3 b/test/unit/regression/operator_overload.c3 index 6936a852c..4d14e6594 100644 --- a/test/unit/regression/operator_overload.c3 +++ b/test/unit/regression/operator_overload.c3 @@ -15,7 +15,7 @@ fn int Abc.mul_abc(Abc abc, int self) @operator_s(*) => self * abc.a; fn Abc Abc.negate(self) @operator(~) => { ~self.a }; fn Abc Abc.negate2(self) @operator(-) => { -self.a }; fn Abc Abc.shr2(self, int x) @operator(>>) => { self.a >> x }; -fn Abc Abc.shl2(self, int x) @operator(<<) @local { b++; return { self.a << x }; } +fn Abc Abc.shl2(self, int x) @operator(<<) { b++; return { self.a << x }; } fn Abc Abc.shl(self, Abc x) @operator(<<) => { self.a << x.a }; fn Abc Abc.div(self, Abc abc) @operator(/) => { self.a / abc.a }; fn Abc Abc.rem(self, Abc abc) @operator(%) => { self.a % abc.a };