diff --git a/lib/std/bits.c3 b/lib/std/bits.c3 index 64ada6e1a..02c5d873c 100644 --- a/lib/std/bits.c3 +++ b/lib/std/bits.c3 @@ -12,21 +12,21 @@ macro reverse(i) => $$bitreverse(i); macro bswap(i) @builtin => $$bswap(i); -macro uint[<*>].popcount(uint[<*>] i) => $$popcount(i); -macro uint[<*>].ctz(uint[<*>] i) => $$ctz(i); -macro uint[<*>].clz(uint[<*>] i) => $$clz(i); +macro uint[<*>].popcount(self) => $$popcount(self); +macro uint[<*>].ctz(self) => $$ctz(self); +macro uint[<*>].clz(self) => $$clz(self); macro uint[<*>] uint[<*>].fshl(uint[<*>] hi, uint[<*>] lo, uint[<*>] shift) => $$fshl(hi, lo, shift); macro uint[<*>] uint[<*>].fshr(uint[<*>] hi, uint[<*>] lo, uint[<*>] shift) => $$fshr(hi, lo, shift); -macro uint[<*>] uint[<*>].rotl(uint[<*>] i, uint[<*>] shift) => $$fshl(i, i, shift); -macro uint[<*>] uint[<*>].rotr(uint[<*>] i, uint[<*>] shift) => $$fshr(i, i, shift); +macro uint[<*>] uint[<*>].rotl(self, uint[<*>] shift) => $$fshl(self, self, shift); +macro uint[<*>] uint[<*>].rotr(self, uint[<*>] shift) => $$fshr(self, self, shift); -macro int[<*>].popcount(int[<*>] i) => $$popcount(i); -macro int[<*>].ctz(int[<*>] i) => $$ctz(i); -macro int[<*>].clz(int[<*>] i) => $$clz(i); +macro int[<*>].popcount(self) => $$popcount(self); +macro int[<*>].ctz(self) => $$ctz(self); +macro int[<*>].clz(self) => $$clz(self); macro int[<*>] int[<*>].fshl(int[<*>] hi, int[<*>] lo, int[<*>] shift) => $$fshl(hi, lo, shift); macro int[<*>] int[<*>].fshr(int[<*>] hi, int[<*>] lo, int[<*>] shift) => $$fshr(hi, lo, shift); -macro int[<*>] int[<*>].rotl(int[<*>] i, int[<*>] shift) => $$fshl(i, i, shift); -macro int[<*>] int[<*>].rotr(int[<*>] i, int[<*>] shift) => $$fshr(i, i, shift); +macro int[<*>] int[<*>].rotl(self, int[<*>] shift) => $$fshl(self, self, shift); +macro int[<*>] int[<*>].rotr(self, int[<*>] shift) => $$fshr(self, self, shift); macro ushort[<*>].popcount(ushort[<*>] i) => $$popcount(i); macro ushort[<*>].ctz(ushort[<*>] i) => $$ctz(i); @@ -92,82 +92,82 @@ macro int128[<*>] int128[<*>].fshr(int128[<*>] hi, int128[<*>] lo, int128[<*>] s macro int128[<*>] int128[<*>].rotl(int128[<*>] i, int128[<*>] shift) => $$fshl(i, i, shift); macro int128[<*>] int128[<*>].rotr(int128[<*>] i, int128[<*>] shift) => $$fshr(i, i, shift); -macro uint.popcount(uint i) => $$popcount(i); -macro uint.ctz(uint i) => $$ctz(i); -macro uint.clz(uint i) => $$clz(i); +macro uint.popcount(self) => $$popcount(i); +macro uint.ctz(self) => $$ctz(i); +macro uint.clz(self) => $$clz(i); macro uint uint.fshl(uint hi, uint lo, uint shift) => $$fshl(hi, lo, shift); macro uint uint.fshr(uint hi, uint lo, uint shift) => $$fshr(hi, lo, shift); macro uint uint.rotl(uint i, uint shift) => $$fshl(i, i, shift); macro uint uint.rotr(uint i, uint shift) => $$fshr(i, i, shift); -macro int.popcount(int i) => $$popcount(i); -macro int.ctz(int i) => $$ctz(i); -macro int.clz(int i) => $$clz(i); +macro int.popcount(self) => $$popcount(i); +macro int.ctz(self) => $$ctz(i); +macro int.clz(self) => $$clz(i); macro int int.fshl(int hi, int lo, int shift) => $$fshl(hi, lo, shift); macro int int.fshr(int hi, int lo, int shift) => $$fshr(hi, lo, shift); macro int int.rotl(int i, int shift) => $$fshl(i, i, shift); macro int int.rotr(int i, int shift) => $$fshr(i, i, shift); -macro ushort.popcount(ushort i) => $$popcount(i); -macro ushort.ctz(ushort i) => $$ctz(i); -macro ushort.clz(ushort i) => $$clz(i); +macro ushort.popcount(self) => $$popcount(i); +macro ushort.ctz(self) => $$ctz(i); +macro ushort.clz(self) => $$clz(i); macro ushort ushort.fshl(ushort hi, ushort lo, ushort shift) => $$fshl(hi, lo, shift); macro ushort ushort.fshr(ushort hi, ushort lo, ushort shift) => $$fshr(hi, lo, shift); macro ushort ushort.rotl(ushort i, ushort shift) => $$fshl(i, i, shift); macro ushort ushort.rotr(ushort i, ushort shift) => $$fshr(i, i, shift); -macro short.popcount(short i) => $$popcount(i); -macro short.ctz(short i) => $$ctz(i); -macro short.clz(short i) => $$clz(i); +macro short.popcount(self) => $$popcount(i); +macro short.ctz(self) => $$ctz(i); +macro short.clz(self) => $$clz(i); macro short short.fshl(short hi, short lo, short shift) => $$fshl(hi, lo, shift); macro short short.fshr(short hi, short lo, short shift) => $$fshr(hi, lo, shift); macro short short.rotl(short i, short shift) => $$fshl(i, i, shift); macro short short.rotr(short i, short shift) => $$fshr(i, i, shift); -macro char.popcount(char i) => $$popcount(i); -macro char.ctz(char i) => $$ctz(i); -macro char.clz(char i) => $$clz(i); +macro char.popcount(self) => $$popcount(i); +macro char.ctz(self) => $$ctz(i); +macro char.clz(self) => $$clz(i); macro char char.fshl(char hi, char lo, char shift) => $$fshl(hi, lo, shift); macro char char.fshr(char hi, char lo, char shift) => $$fshr(hi, lo, shift); macro char char.rotl(char i, char shift) => $$fshl(i, i, shift); macro char char.rotr(char i, char shift) => $$fshr(i, i, shift); -macro ichar.popcount(ichar i) => $$popcount(i); -macro ichar.ctz(ichar i) => $$ctz(i); -macro ichar.clz(ichar i) => $$clz(i); +macro ichar.popcount(self) => $$popcount(i); +macro ichar.ctz(self) => $$ctz(i); +macro ichar.clz(self) => $$clz(i); macro ichar ichar.fshl(ichar hi, ichar lo, ichar shift) => $$fshl(hi, lo, shift); macro ichar ichar.fshr(ichar hi, ichar lo, ichar shift) => $$fshr(hi, lo, shift); macro ichar ichar.rotl(ichar i, ichar shift) => $$fshl(i, i, shift); macro ichar ichar.rotr(ichar i, ichar shift) => $$fshr(i, i, shift); -macro ulong.popcount(ulong i) => $$popcount(i); -macro ulong.ctz(ulong i) => $$ctz(i); -macro ulong.clz(ulong i) => $$clz(i); +macro ulong.popcount(self) => $$popcount(i); +macro ulong.ctz(self) => $$ctz(i); +macro ulong.clz(self) => $$clz(i); macro ulong ulong.fshl(ulong hi, ulong lo, ulong shift) => $$fshl(hi, lo, shift); macro ulong ulong.fshr(ulong hi, ulong lo, ulong shift) => $$fshr(hi, lo, shift); macro ulong ulong.rotl(ulong i, ulong shift) => $$fshl(i, i, shift); macro ulong ulong.rotr(ulong i, ulong shift) => $$fshr(i, i, shift); -macro long.popcount(long i) => $$popcount(i); -macro long.ctz(long i) => $$ctz(i); -macro long.clz(long i) => $$clz(i); +macro long.popcount(self) => $$popcount(i); +macro long.ctz(self) => $$ctz(i); +macro long.clz(self) => $$clz(i); macro long long.fshl(long hi, long lo, long shift) => $$fshl(hi, lo, shift); macro long long.fshr(long hi, long lo, long shift) => $$fshr(hi, lo, shift); macro long long.rotl(long i, long shift) => $$fshl(i, i, shift); macro long long.rotr(long i, long shift) => $$fshr(i, i, shift); -macro uint128.popcount(uint128 i) => $$popcount(i); -macro uint128.ctz(uint128 i) => $$ctz(i); -macro uint128.clz(uint128 i) => $$clz(i); +macro uint128.popcount(self) => $$popcount(self); +macro uint128.ctz(self) => $$ctz(self); +macro uint128.clz(self) => $$clz(self); macro uint128 uint128.fshl(uint128 hi, uint128 lo, uint128 shift) => $$fshl(hi, lo, shift); macro uint128 uint128.fshr(uint128 hi, uint128 lo, uint128 shift) => $$fshr(hi, lo, shift); -macro uint128 uint128.rotl(uint128 i, uint128 shift) => $$fshl(i, i, shift); -macro uint128 uint128.rotr(uint128 i, uint128 shift) => $$fshr(i, i, shift); +macro uint128 uint128.rotl(self, uint128 shift) => $$fshl(self, self, shift); +macro uint128 uint128.rotr(self, uint128 shift) => $$fshr(self, self, shift); -macro int128.popcount(int128 i) => $$popcount(i); -macro int128.ctz(int128 i) => $$ctz(i); -macro int128.clz(int128 i) => $$clz(i); +macro int128.popcount(self) => $$popcount(self); +macro int128.ctz(self) => $$ctz(self); +macro int128.clz(self) => $$clz(self); macro int128 int128.fshl(int128 hi, int128 lo, int128 shift) => $$fshl(hi, lo, shift); macro int128 int128.fshr(int128 hi, int128 lo, int128 shift) => $$fshr(hi, lo, shift); -macro int128 int128.rotl(int128 i, int128 shift) => $$fshl(i, i, shift); -macro int128 int128.rotr(int128 i, int128 shift) => $$fshr(i, i, shift); +macro int128 int128.rotl(self, int128 shift) => $$fshl(self, self, shift); +macro int128 int128.rotr(self, int128 shift) => $$fshr(self, self, shift); diff --git a/lib/std/collections/enumset.c3 b/lib/std/collections/enumset.c3 index 81e4db5ca..2465e5ff5 100644 --- a/lib/std/collections/enumset.c3 +++ b/lib/std/collections/enumset.c3 @@ -161,5 +161,5 @@ macro typeid type_for_enum_elements(usz $elements) return ushort.typeid; $default: return char.typeid; - $endswitch; + $endswitch } \ No newline at end of file diff --git a/lib/std/core/allocators/arena_allocator.c3 b/lib/std/core/allocators/arena_allocator.c3 index cc7291a8a..b8e81c853 100644 --- a/lib/std/core/allocators/arena_allocator.c3 +++ b/lib/std/core/allocators/arena_allocator.c3 @@ -12,22 +12,17 @@ struct ArenaAllocator /** * Initialize a memory arena for use using the provided bytes. - * - * @require this != null **/ -fn void ArenaAllocator.init(ArenaAllocator* this, char[] data) +fn void ArenaAllocator.init(&self, char[] data) { - this.function = &arena_allocator_function; - this.data = data; - this.used = 0; + self.function = &arena_allocator_function; + self.data = data; + self.used = 0; } -/** - * @require this != null - **/ -fn void ArenaAllocator.reset(ArenaAllocator* this) +fn void ArenaAllocator.reset(&self) { - this.used = 0; + self.used = 0; } @@ -95,18 +90,17 @@ fn void*! arena_allocator_function(Allocator* data, usz size, usz alignment, usz * @require offset <= mem::MAX_MEMORY_ALIGNMENT `offset too big` * @require offset <= size && offset >= 0 * @require mem::aligned_offset(offset, ArenaAllocatorHeader.alignof) == offset - * @require this != null **/ -fn void*! ArenaAllocator._alloc(ArenaAllocator* this, usz size, usz alignment, usz offset) +fn void*! ArenaAllocator._alloc(&self, usz size, usz alignment, usz offset) { - usz total_len = this.data.len; + usz total_len = self.data.len; if (size > total_len) return AllocationFailure.CHUNK_TOO_LARGE?; - void* start_mem = this.data.ptr; - void* unaligned_pointer_to_offset = start_mem + this.used + ArenaAllocatorHeader.sizeof + offset; + void* start_mem = self.data.ptr; + void* unaligned_pointer_to_offset = start_mem + self.used + ArenaAllocatorHeader.sizeof + offset; void* aligned_pointer_to_offset = mem::aligned_pointer(unaligned_pointer_to_offset, alignment); - usz end = (usz)(aligned_pointer_to_offset - this.data.ptr) + size - offset; + usz end = (usz)(aligned_pointer_to_offset - self.data.ptr) + size - offset; if (end > total_len) return AllocationFailure.OUT_OF_MEMORY?; - this.used = end; + self.used = end; void* mem = aligned_pointer_to_offset - offset; ArenaAllocatorHeader* header = mem - ArenaAllocatorHeader.sizeof; header.size = size; @@ -121,33 +115,32 @@ fn void*! ArenaAllocator._alloc(ArenaAllocator* this, usz size, usz alignment, u * @require offset <= mem::MAX_MEMORY_ALIGNMENT `offset too big` * @require offset <= size && offset >= 0 * @require mem::aligned_offset(offset, ArenaAllocatorHeader.alignof) == offset - * @require this != null **/ -fn void*! ArenaAllocator._realloc(ArenaAllocator* this, void *old_pointer, usz size, usz alignment, usz offset) +fn void*! ArenaAllocator._realloc(&self, void *old_pointer, usz size, usz alignment, usz offset) { - assert(old_pointer >= this.data.ptr, "Pointer originates from a different allocator."); - usz total_len = this.data.len; + assert(old_pointer >= self.data.ptr, "Pointer originates from a different allocator."); + usz total_len = self.data.len; if (size > total_len) return AllocationFailure.CHUNK_TOO_LARGE?; ArenaAllocatorHeader* header = old_pointer - ArenaAllocatorHeader.sizeof; usz old_size = header.size; // Do last allocation and alignment match? - if (&this.data[this.used] == old_pointer + old_size && mem::ptr_is_aligned(old_pointer + offset, alignment)) + if (&self.data[self.used] == old_pointer + old_size && mem::ptr_is_aligned(old_pointer + offset, alignment)) { if (old_size >= size) { - this.used -= old_size - size; + self.used -= old_size - size; } else { - usz new_used = this.used + size - old_size; + usz new_used = self.used + size - old_size; if (new_used > total_len) return AllocationFailure.OUT_OF_MEMORY?; - this.used = new_used; + self.used = new_used; } header.size = size; return old_pointer; } // Otherwise just allocate new memory. - void* mem = this._alloc(size, alignment, offset)!; + void* mem = self._alloc(size, alignment, offset)!; mem::copy(mem, old_pointer, old_size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT); return mem; } \ No newline at end of file diff --git a/lib/std/core/allocators/dynamic_arena.c3 b/lib/std/core/allocators/dynamic_arena.c3 index bb94bcb88..79c955583 100644 --- a/lib/std/core/allocators/dynamic_arena.c3 +++ b/lib/std/core/allocators/dynamic_arena.c3 @@ -14,38 +14,34 @@ struct DynamicArenaAllocator /** * @require page_size >= 128 - * @require this != null **/ -fn void DynamicArenaAllocator.init(DynamicArenaAllocator* this, usz page_size, Allocator* using = mem::heap()) +fn void DynamicArenaAllocator.init(&self, usz page_size, Allocator* using = mem::heap()) { - this.function = &dynamic_arena_allocator_function; - this.page = null; - this.unused_page = null; - this.page_size = page_size; - this.backing_allocator = using; + self.function = &dynamic_arena_allocator_function; + self.page = null; + self.unused_page = null; + self.page_size = page_size; + self.backing_allocator = using; } -/** - * @param [&inout] this "The allocator to free" - **/ -fn void DynamicArenaAllocator.free(DynamicArenaAllocator* this) +fn void DynamicArenaAllocator.free(&self) { - DynamicArenaPage* page = this.page; + DynamicArenaPage* page = self.page; while (page) { DynamicArenaPage* next_page = page.prev_arena; - free(page, .using = this.backing_allocator); + free(page, .using = self.backing_allocator); page = next_page; } - page = this.unused_page; + page = self.unused_page; while (page) { DynamicArenaPage* next_page = page.prev_arena; - free(page, .using = this.backing_allocator); + free(page, .using = self.backing_allocator); page = next_page; } - this.page = null; - this.unused_page = null; + self.page = null; + self.unused_page = null; } struct DynamicArenaPage @local @@ -63,12 +59,12 @@ struct DynamicArenaChunk @local } /** - * @require ptr && this - * @require this.page `tried to free pointer on invalid allocator` + * @require ptr + * @require self.page `tried to free pointer on invalid allocator` */ -fn void DynamicArenaAllocator.free_ptr(DynamicArenaAllocator* this, void* ptr) @local +fn void DynamicArenaAllocator.free_ptr(&self, void* ptr) @local { - DynamicArenaPage* current_page = this.page; + DynamicArenaPage* current_page = self.page; if (ptr == current_page.current_stack_ptr) { current_page.used = (usz)((ptr - DEFAULT_SIZE_PREFIX) - current_page.memory); @@ -78,11 +74,11 @@ fn void DynamicArenaAllocator.free_ptr(DynamicArenaAllocator* this, void* ptr) @ /** * @require old_pointer && size > 0 - * @require this.page `tried to realloc pointer on invalid allocator` + * @require self.page `tried to realloc pointer on invalid allocator` */ -fn void*! DynamicArenaAllocator._realloc(DynamicArenaAllocator* this, void* old_pointer, usz size, usz alignment, usz offset) @local +fn void*! DynamicArenaAllocator._realloc(&self, void* old_pointer, usz size, usz alignment, usz offset) @local { - DynamicArenaPage* current_page = this.page; + DynamicArenaPage* current_page = self.page; alignment = alignment_for_allocation(alignment); usz* old_size_ptr = old_pointer - DEFAULT_SIZE_PREFIX; usz old_size = *old_size_ptr; @@ -105,15 +101,15 @@ fn void*! DynamicArenaAllocator._realloc(DynamicArenaAllocator* this, void* old_ current_page.used += add_size; return old_pointer; } - void* new_mem = this._alloc(size, alignment, offset)!; + void* new_mem = self._alloc(size, alignment, offset)!; mem::copy(new_mem, old_pointer, old_size, mem::DEFAULT_MEM_ALIGNMENT); return new_mem; } -fn void DynamicArenaAllocator.reset(DynamicArenaAllocator* this) @private +fn void DynamicArenaAllocator.reset(&self) @private { - DynamicArenaPage* page = this.page; - DynamicArenaPage** unused_page_ptr = &this.unused_page; + DynamicArenaPage* page = self.page; + DynamicArenaPage** unused_page_ptr = &self.unused_page; while (page) { DynamicArenaPage* next_page = page.prev_arena; @@ -123,24 +119,24 @@ fn void DynamicArenaAllocator.reset(DynamicArenaAllocator* this) @private page.prev_arena = prev_unused; page = next_page; } - this.page = page; + self.page = page; } /** * @require math::is_power_of_2(alignment) * @require size > 0 */ -fn void*! DynamicArenaAllocator._alloc_new(DynamicArenaAllocator* this, usz size, usz alignment, usz offset) @local +fn void*! DynamicArenaAllocator._alloc_new(&self, usz size, usz alignment, usz offset) @local { // First, make sure that we can align it, extending the page size if needed. - usz page_size = max(this.page_size, mem::aligned_offset(size + DynamicArenaChunk.sizeof + offset, alignment) - offset); + usz page_size = max(self.page_size, mem::aligned_offset(size + DynamicArenaChunk.sizeof + offset, alignment) - offset); // Grab the page without alignment (we do it ourselves) - void* mem = this.backing_allocator.alloc(page_size)!; - DynamicArenaPage*! page = malloc(DynamicArenaPage, .using = this.backing_allocator); + void* mem = self.backing_allocator.alloc(page_size)!; + DynamicArenaPage*! page = malloc(DynamicArenaPage, .using = self.backing_allocator); if (catch err = page) { - free(mem, .using = this.backing_allocator); + free(mem, .using = self.backing_allocator); return err?; } page.memory = mem; @@ -148,10 +144,10 @@ fn void*! DynamicArenaAllocator._alloc_new(DynamicArenaAllocator* this, usz size assert(mem_start + size < mem + page_size); DynamicArenaChunk* chunk = (DynamicArenaChunk*)mem_start - 1; chunk.size = size; - page.prev_arena = this.page; + page.prev_arena = self.page; page.total = page_size; page.used = mem_start + size - page.memory; - this.page = page; + self.page = page; page.current_stack_ptr = mem_start; return mem_start; } @@ -159,36 +155,35 @@ fn void*! DynamicArenaAllocator._alloc_new(DynamicArenaAllocator* this, usz size /** * @require !alignment || math::is_power_of_2(alignment) * @require size > 0 - * @require this */ -fn void*! DynamicArenaAllocator._alloc(DynamicArenaAllocator* this, usz size, usz alignment, usz offset) @local +fn void*! DynamicArenaAllocator._alloc(&self, usz size, usz alignment, usz offset) @local { alignment = alignment_for_allocation(alignment); - DynamicArenaPage* page = this.page; - if (!page && this.unused_page) + DynamicArenaPage* page = self.page; + if (!page && self.unused_page) { - this.page = page = this.unused_page; - this.unused_page = page.prev_arena; + self.page = page = self.unused_page; + self.unused_page = page.prev_arena; page.prev_arena = null; } - if (!page) return this._alloc_new(size, alignment, offset); + if (!page) return self._alloc_new(size, alignment, offset); void* start = mem::aligned_pointer(page.memory + page.used + DynamicArenaChunk.sizeof + offset, alignment) - offset; usz new_used = start - page.memory + size; if ALLOCATE_NEW: (new_used > page.total) { - if ((page = this.unused_page)) + if ((page = self.unused_page)) { start = mem::aligned_pointer(page.memory + page.used + DynamicArenaChunk.sizeof + offset, alignment) - offset; new_used = start + size - page.memory; if (page.total >= new_used) { - this.unused_page = page.prev_arena; - page.prev_arena = this.page; - this.page = page; + self.unused_page = page.prev_arena; + page.prev_arena = self.page; + self.page = page; break ALLOCATE_NEW; } } - return this._alloc_new(size, alignment, offset); + return self._alloc_new(size, alignment, offset); } page.used = new_used; diff --git a/lib/std/core/allocators/heap_allocator.c3 b/lib/std/core/allocators/heap_allocator.c3 index d8a8b7c73..86f3e2b48 100644 --- a/lib/std/core/allocators/heap_allocator.c3 +++ b/lib/std/core/allocators/heap_allocator.c3 @@ -13,16 +13,15 @@ struct SimpleHeapAllocator } /** - * @require this "Unexpectedly missing the allocator" * @require allocator "An underlying memory provider must be given" - * @require !this.free_list "The allocator may not be already initialized" + * @require !self.free_list "The allocator may not be already initialized" **/ -fn void SimpleHeapAllocator.init(SimpleHeapAllocator* this, MemoryAllocFn allocator) +fn void SimpleHeapAllocator.init(&self, MemoryAllocFn allocator) { - this.alloc_fn = allocator; + self.alloc_fn = allocator; static AllocatorFunction alloc_fn = &simple_heap_allocator_function; - this.allocator = { alloc_fn }; - this.free_list = null; + self.allocator = { alloc_fn }; + self.free_list = null; } /** @@ -65,36 +64,36 @@ fn void*! simple_heap_allocator_function(Allocator* this, usz size, usz alignmen } /** - * @require this && old_pointer && bytes > 0 + * @require old_pointer && bytes > 0 **/ -fn void*! SimpleHeapAllocator._realloc(SimpleHeapAllocator* this, void* old_pointer, usz bytes) @local +fn void*! SimpleHeapAllocator._realloc(&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 = this._alloc(bytes)!; + void* new = self._alloc(bytes)!; usz max_to_copy = math::min(block.size, bytes); mem::copy(new, old_pointer, max_to_copy); - this._free(old_pointer); + self._free(old_pointer); return new; } -fn void*! SimpleHeapAllocator._calloc(SimpleHeapAllocator* this, usz bytes) @local +fn void*! SimpleHeapAllocator._calloc(&self, usz bytes) @local { - void* data = this._alloc(bytes)!; + void* data = self._alloc(bytes)!; mem::clear(data, bytes, mem::DEFAULT_MEM_ALIGNMENT); return data; } -fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @local +fn void*! SimpleHeapAllocator._alloc(&self, usz bytes) @local { usz aligned_bytes = mem::aligned_offset(bytes, mem::DEFAULT_MEM_ALIGNMENT); - if (!this.free_list) + if (!self.free_list) { - this.add_block(aligned_bytes)!; + self.add_block(aligned_bytes)!; } - Header* current = this.free_list; + Header* current = self.free_list; Header* previous = current; while (current) { @@ -103,7 +102,7 @@ fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @loca case current.size >= aligned_bytes && current.size <= aligned_bytes + Header.sizeof + 64: if (current == previous) { - this.free_list = current.next; + self.free_list = current.next; } else { @@ -115,9 +114,9 @@ fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @loca Header* unallocated = (Header*)((char*)current + aligned_bytes + Header.sizeof); unallocated.size = current.size - aligned_bytes; unallocated.next = current.next; - if (current == this.free_list) + if (current == self.free_list) { - this.free_list = unallocated; + self.free_list = unallocated; } else { @@ -131,22 +130,22 @@ fn void*! SimpleHeapAllocator._alloc(SimpleHeapAllocator* this, usz bytes) @loca current = current.next; } } - this.add_block(aligned_bytes)!; - return this.alloc(aligned_bytes); + self.add_block(aligned_bytes)!; + return self.alloc(aligned_bytes); } -fn void! SimpleHeapAllocator.add_block(SimpleHeapAllocator* this, usz aligned_bytes) @local +fn void! SimpleHeapAllocator.add_block(&self, usz aligned_bytes) @local { assert(mem::aligned_offset(aligned_bytes, mem::DEFAULT_MEM_ALIGNMENT) == aligned_bytes); - char[] result = this.alloc_fn(aligned_bytes + Header.sizeof)!; + 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; - this._free(new_block + 1); + self._free(new_block + 1); } -fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) @local +fn void SimpleHeapAllocator._free(&self, void* ptr) @local { // Empty ptr -> do nothing. if (!ptr) return; @@ -154,15 +153,15 @@ fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) @local // Find the block header. Header* block = (Header*)ptr - 1; - // No free list? Then just return this. - if (!this.free_list) + // No free list? Then just return self. + if (!self.free_list) { - this.free_list = block; + self.free_list = block; return; } // Find where in the list it should be inserted. - Header* current = this.free_list; + Header* current = self.free_list; Header* prev = current; while (current) { @@ -195,7 +194,7 @@ fn void SimpleHeapAllocator._free(SimpleHeapAllocator* this, void* ptr) @local if (prev == current) { // Swap new start of free list - this.free_list = block; + self.free_list = block; } else { diff --git a/lib/std/core/allocators/on_stack_allocator.c3 b/lib/std/core/allocators/on_stack_allocator.c3 index 8afa0e593..ae49e93ac 100644 --- a/lib/std/core/allocators/on_stack_allocator.c3 +++ b/lib/std/core/allocators/on_stack_allocator.c3 @@ -19,39 +19,34 @@ struct OnStackAllocatorExtraChunk @local /** * Initialize a memory arena for use using the provided bytes. - * - * @require this != null **/ -fn void OnStackAllocator.init(OnStackAllocator* this, char[] data, Allocator* using = mem::heap()) +fn void OnStackAllocator.init(&self, char[] data, Allocator* using = mem::heap()) { - this.function = &on_stack_allocator_function; - this.data = data; - this.backing_allocator = using; - this.used = 0; + self.function = &on_stack_allocator_function; + self.data = data; + self.backing_allocator = using; + self.used = 0; } -/** - * @require this != null - **/ -fn void OnStackAllocator.free(OnStackAllocator* this) +fn void OnStackAllocator.free(&self) { - OnStackAllocatorExtraChunk* chunk = this.chunk; + OnStackAllocatorExtraChunk* chunk = self.chunk; while (chunk) { if (chunk.is_aligned) { - this.backing_allocator.free_aligned(chunk.data)!!; + self.backing_allocator.free_aligned(chunk.data)!!; } else { - this.backing_allocator.free(chunk.data)!!; + self.backing_allocator.free(chunk.data)!!; } void* old = chunk; chunk = chunk.prev; - this.backing_allocator.free(old)!!; + self.backing_allocator.free(old)!!; } - this.chunk = null; - this.used = 0; + self.chunk = null; + self.used = 0; } struct OnStackAllocatorHeader diff --git a/lib/std/core/allocators/temp_allocator.c3 b/lib/std/core/allocators/temp_allocator.c3 index 15a992c07..c35b0d402 100644 --- a/lib/std/core/allocators/temp_allocator.c3 +++ b/lib/std/core/allocators/temp_allocator.c3 @@ -31,8 +31,8 @@ struct TempAllocatorPage char[*] data; } -macro usz TempAllocatorPage.pagesize(TempAllocatorPage* page) => page.size & ~PAGE_IS_ALIGNED; -macro bool TempAllocatorPage.is_aligned(TempAllocatorPage* page) => page.size & PAGE_IS_ALIGNED == PAGE_IS_ALIGNED; +macro usz TempAllocatorPage.pagesize(&self) => self.size & ~PAGE_IS_ALIGNED; +macro bool TempAllocatorPage.is_aligned(&self) => self.size & PAGE_IS_ALIGNED == PAGE_IS_ALIGNED; /** * @require size >= 16 @@ -86,41 +86,41 @@ fn void*! temp_allocator_function(Allocator* data, usz size, usz alignment, usz unreachable(); } -fn void! TempAllocator._free(TempAllocator* this, void* old_pointer) @local +fn void! TempAllocator._free(&self, void* old_pointer) @local { usz old_size = *(usz*)(old_pointer - DEFAULT_SIZE_PREFIX); - if (old_pointer + old_size == &this.data[this.used]) + if (old_pointer + old_size == &self.data[self.used]) { - this.used -= old_size; + self.used -= old_size; } } -fn void! TempAllocator._reset(TempAllocator* this, usz mark) @local +fn void! TempAllocator._reset(&self, usz mark) @local { - TempAllocatorPage *last_page = this.last_page; + TempAllocatorPage *last_page = self.last_page; while (last_page && last_page.mark > mark) { TempAllocatorPage *to_free = last_page; last_page = last_page.prev_page; - this._free_page(to_free)!; + self._free_page(to_free)!; } - this.last_page = last_page; - this.used = mark; + self.last_page = last_page; + self.used = mark; } -fn void! TempAllocator._free_page(TempAllocator* this, TempAllocatorPage* page) @inline @local +fn void! TempAllocator._free_page(&self, TempAllocatorPage* page) @inline @local { void* mem = page.start; - if (page.is_aligned()) return this.backing_allocator.free_aligned(mem); - return this.backing_allocator.free(mem); + if (page.is_aligned()) return self.backing_allocator.free_aligned(mem); + return self.backing_allocator.free(mem); } -fn void*! TempAllocator._realloc_page(TempAllocator* this, TempAllocatorPage* page, usz size, usz alignment, usz offset) @inline @local +fn void*! TempAllocator._realloc_page(&self, TempAllocatorPage* page, usz size, usz alignment, usz offset) @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 = &this.last_page; + TempAllocatorPage **pointer_to_prev = &self.last_page; // Remove the page from the list while (*pointer_to_prev != page) { @@ -129,32 +129,32 @@ fn void*! TempAllocator._realloc_page(TempAllocator* this, TempAllocatorPage* pa *pointer_to_prev = page.prev_page; usz page_size = page.pagesize(); // Clear on size > original size. - void* data = this._alloc(size, alignment, offset, false)!; + void* data = self._alloc(size, alignment, offset, false)!; mem::copy(data, &page.data[0], page_size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT); if (page.is_aligned()) { - this.backing_allocator.free_aligned(real_pointer)!; + self.backing_allocator.free_aligned(real_pointer)!; } else { - this.backing_allocator.free(real_pointer)!; + self.backing_allocator.free(real_pointer)!; } return data; } -fn void*! TempAllocator._realloc(TempAllocator* this, void* pointer, usz size, usz alignment, usz offset) @inline @local +fn void*! TempAllocator._realloc(&self, void* pointer, usz size, usz alignment, usz offset) @inline @local { TempAllocatorChunk *chunk = pointer - TempAllocatorChunk.sizeof; if (chunk.size == (usz)-1) { - assert(this.last_page, "Realloc of non temp pointer"); + assert(self.last_page, "Realloc of non temp pointer"); // First grab the page TempAllocatorPage *page = pointer - TempAllocatorPage.sizeof; - return this._realloc_page(page, size, alignment, offset); + return self._realloc_page(page, size, alignment, offset); } // TODO optimize last allocation - TempAllocatorChunk* data = this._alloc(size, alignment, offset, size > chunk.size)!; + TempAllocatorChunk* data = self._alloc(size, alignment, offset, size > chunk.size)!; mem::copy(data, pointer, chunk.size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT); return data; @@ -164,12 +164,11 @@ fn void*! TempAllocator._realloc(TempAllocator* this, void* pointer, usz size, u * @require math::is_power_of_2(alignment) * @require size > 0 * @require alignment <= mem::MAX_MEMORY_ALIGNMENT `alignment too big` - * @require this != null **/ -fn void*! TempAllocator._alloc(TempAllocator* this, usz size, usz alignment, usz offset, bool clear) @local +fn void*! TempAllocator._alloc(&self, usz size, usz alignment, usz offset, bool clear) @local { - void* start_mem = &this.data; - void* starting_ptr = start_mem + this.used; + void* start_mem = &self.data; + void* starting_ptr = start_mem + self.used; void* aligned_header_start = mem::aligned_pointer(starting_ptr, TempAllocatorChunk.alignof); void* mem = aligned_header_start + TempAllocatorChunk.sizeof; if (alignment > TempAllocatorChunk.alignof) @@ -179,11 +178,11 @@ fn void*! TempAllocator._alloc(TempAllocator* this, usz size, usz alignment, usz usz new_usage = (usz)(mem - start_mem) + size; // Arena alignment, simple! - if (new_usage <= this.capacity) + if (new_usage <= self.capacity) { TempAllocatorChunk* chunk_start = mem - TempAllocatorChunk.sizeof; chunk_start.size = size; - this.used = new_usage; + self.used = new_usage; if (clear) mem::clear(mem, size, mem::DEFAULT_MEM_ALIGNMENT); return mem; } @@ -198,11 +197,11 @@ fn void*! TempAllocator._alloc(TempAllocator* this, usz size, usz alignment, usz usz total_alloc_size = TempAllocatorPage.sizeof + size; if (clear) { - page = this.backing_allocator.calloc_aligned(total_alloc_size, alignment, TempAllocatorPage.sizeof + offset)!; + page = self.backing_allocator.calloc_aligned(total_alloc_size, alignment, TempAllocatorPage.sizeof + offset)!; } else { - page = this.backing_allocator.alloc_aligned(total_alloc_size, alignment, TempAllocatorPage.sizeof + offset)!; + page = self.backing_allocator.alloc_aligned(total_alloc_size, alignment, TempAllocatorPage.sizeof + offset)!; } page.start = page; page.size = size | PAGE_IS_ALIGNED; @@ -212,7 +211,7 @@ fn void*! TempAllocator._alloc(TempAllocator* this, usz size, usz alignment, usz // Here we might need to pad usz padded_header_size = mem::aligned_offset(TempAllocatorPage.sizeof, mem::DEFAULT_MEM_ALIGNMENT); usz total_alloc_size = padded_header_size + size; - void* alloc = (clear ? this.backing_allocator.calloc(total_alloc_size) : this.backing_allocator.alloc(total_alloc_size))!; + void* alloc = (clear ? self.backing_allocator.calloc(total_alloc_size) : self.backing_allocator.alloc(total_alloc_size))!; // Find the page. page = alloc + padded_header_size - TempAllocatorPage.sizeof; @@ -225,16 +224,16 @@ fn void*! TempAllocator._alloc(TempAllocator* this, usz size, usz alignment, usz // Mark it as a page page.ident = ~(usz)0; // Store when it was created - page.mark = ++this.used; + page.mark = ++self.used; // Hook up the page. - page.prev_page = this.last_page; - this.last_page = page; + page.prev_page = self.last_page; + self.last_page = page; return &page.data[0]; } -fn void TempAllocator.print_pages(TempAllocator* this, File f) +fn void TempAllocator.print_pages(&self, File f) { - TempAllocatorPage *last_page = this.last_page; + TempAllocatorPage *last_page = self.last_page; if (!last_page) { f.printf("No pages.\n"); diff --git a/lib/std/core/allocators/tracking_allocator.c3 b/lib/std/core/allocators/tracking_allocator.c3 index cee89d3e5..a5d60f9f8 100644 --- a/lib/std/core/allocators/tracking_allocator.c3 +++ b/lib/std/core/allocators/tracking_allocator.c3 @@ -20,35 +20,34 @@ struct TrackingAllocator } /** - * Initialize a memory arena for use using the provided bytes. + * Initialize a tracking allocator to wrap (and track) another allocator. * - * @require this != null + * @param [&inout] using "The allocator to track" **/ -fn void TrackingAllocator.init(TrackingAllocator* this, Allocator* using) +fn void TrackingAllocator.init(&self, Allocator* using) { - *this = { .inner_allocator = using, .allocator.function = &tracking_allocator_fn }; - this.map.init(.using = using); + *self = { .inner_allocator = using, .allocator.function = &tracking_allocator_fn }; + self.map.init(.using = using); } /** * Free this tracking allocator. - * @param [&inout] this "The allocator to modify" **/ -fn void TrackingAllocator.free(TrackingAllocator* this) +fn void TrackingAllocator.free(&self) { - this.map.free(); - *this = {}; + self.map.free(); + *self = {}; } /** * @return "the total allocated memory not yet freed." **/ -fn usz TrackingAllocator.allocated(TrackingAllocator* this) +fn usz TrackingAllocator.allocated(&self) { usz allocated = 0; @pool() { - foreach (usz allocation : this.map.value_tlist()) allocated += allocation; + foreach (usz allocation : self.map.value_tlist()) allocated += allocation; }; return allocated; } @@ -56,17 +55,17 @@ fn usz TrackingAllocator.allocated(TrackingAllocator* this) /** * @return "the total memory allocated (freed or not)." **/ -fn usz TrackingAllocator.total_allocated(TrackingAllocator* this) => this.mem_total; +fn usz TrackingAllocator.total_allocated(&self) => self.mem_total; /** * @return "the total number of allocations (freed or not)." **/ -fn usz TrackingAllocator.total_allocation_count(TrackingAllocator* this) => this.allocs_total; +fn usz TrackingAllocator.total_allocation_count(&self) => self.allocs_total; /** * @return "the number of non-freed allocations." **/ -fn usz TrackingAllocator.allocation_count(TrackingAllocator* this) => this.map.count; +fn usz TrackingAllocator.allocation_count(&self) => self.map.count; /** * @param [inout] data diff --git a/lib/std/core/bitorder.c3 b/lib/std/core/bitorder.c3 index 51bab6dc4..4fdec515e 100644 --- a/lib/std/core/bitorder.c3 +++ b/lib/std/core/bitorder.c3 @@ -139,8 +139,9 @@ macro is_bitorder($Type) $case UInt128BE: $case Int128BE: return true; + $default: + return false; $endswitch - return false; } macro bool is_array_or_sub_of_char(bytes) @@ -156,8 +157,9 @@ macro bool is_array_or_sub_of_char(bytes) $case SUBARRAY: var $Inner = $typefrom($typeof(bytes).inner); return $Inner.typeid == char.typeid; + $default: + return false; $endswitch - return false; } macro bool is_arrayptr_or_sub_of_char(bytes) @@ -172,6 +174,7 @@ macro bool is_arrayptr_or_sub_of_char(bytes) $case SUBARRAY: var $Inner = $typefrom($typeof(bytes).inner); return $Inner.typeid == char.typeid; + $default: + return false; $endswitch - return false; } \ No newline at end of file diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index a756dd455..9ebef4e77 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -79,7 +79,6 @@ fn void default_panic(String message, String file, String function, uint line) { CallstackElement* stack = $$stacktrace(); $if $defined(io::stderr) && $defined(File.printf): - if (stack) stack = stack.prev; if (stack) { @@ -99,7 +98,6 @@ fn void default_panic(String message, String file, String function, uint line) if (stack == stack.prev) break; stack = stack.prev; } - $endif $$trap(); } diff --git a/lib/std/core/dstring.c3 b/lib/std/core/dstring.c3 index 95b51bf99..b989006a1 100644 --- a/lib/std/core/dstring.c3 +++ b/lib/std/core/dstring.c3 @@ -5,22 +5,22 @@ def DString = distinct void*; const usz MIN_CAPACITY @private = 16; /** - * @require !str.data() "String already initialized" + * @require !self.data() "String already initialized" **/ -fn void DString.init(DString *str, usz capacity = MIN_CAPACITY, Allocator* using = mem::heap()) +fn void DString.init(&self, usz capacity = MIN_CAPACITY, Allocator* using = mem::heap()) { if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY; StringData* data = malloc(StringData, 1, .using = using, .end_padding = capacity); data.allocator = using; data.len = 0; data.capacity = capacity; - *str = (DString)data; + *self = (DString)data; } /** - * @require !str.data() "String already initialized" + * @require !self.data() "String already initialized" **/ -fn void DString.tinit(DString *str, usz capacity = MIN_CAPACITY) => str.init(capacity, mem::temp()) @inline; +fn void DString.tinit(&self, usz capacity = MIN_CAPACITY) => self.init(capacity, mem::temp()) @inline; fn DString new_with_capacity(usz capacity, Allocator* using = mem::heap()) { @@ -45,24 +45,24 @@ fn DString new(String c = "", Allocator* using = mem::heap()) fn DString tnew(String s = "") => new(s, mem::temp()) @inline; -fn DString DString.new_concat(DString a, DString b, Allocator* using = mem::heap()) +fn DString DString.new_concat(self, DString b, Allocator* using = mem::heap()) { DString string; - string.init(a.len() + b.len(), using); - string.append(a); + string.init(self.len() + b.len(), using); + string.append(self); string.append(b); return string; } -fn DString DString.new_tconcat(DString a, DString b) => a.new_concat(b, mem::temp()); +fn DString DString.new_tconcat(self, DString b) => self.new_concat(b, mem::temp()); -fn ZString DString.zstr(DString str) +fn ZString DString.zstr(self) { - StringData* data = str.data(); + StringData* data = self.data(); if (!data) return ""; if (data.capacity == data.len) { - str.reserve(1); + self.reserve(1); data.chars[data.len] = 0; } else if (data.chars[data.len] != 0) @@ -72,56 +72,56 @@ fn ZString DString.zstr(DString str) return (ZString)&data.chars[0]; } -fn usz DString.capacity(DString this) +fn usz DString.capacity(self) { - if (!this) return 0; - return this.data().capacity; + if (!self) return 0; + return self.data().capacity; } -fn usz DString.len(DString this) +fn usz DString.len(self) { - if (!this) return 0; - return this.data().len; + if (!self) return 0; + return self.data().len; } /** - * @require new_size <= this.len() + * @require new_size <= self.len() */ -fn void DString.chop(DString this, usz new_size) +fn void DString.chop(self, usz new_size) { - if (!this) return; - this.data().len = new_size; + if (!self) return; + self.data().len = new_size; } -fn String DString.str(DString str) +fn String DString.str(self) { - StringData* data = (StringData*)str; + StringData* data = (StringData*)self; if (!data) return ""; return (String)data.chars[:data.len]; } -fn void DString.append_utf32(DString* str, Char32[] chars) +fn void DString.append_utf32(&self, Char32[] chars) { - str.reserve(chars.len); + self.reserve(chars.len); foreach (Char32 c : chars) { - str.append_char32(c); + self.append_char32(c); } } /** - * @require index < str.len() + * @require index < self.len() **/ -fn void DString.set(DString str, usz index, char c) +fn void DString.set(self, usz index, char c) { - str.data().chars[index] = c; + self.data().chars[index] = c; } -fn void DString.append_repeat(DString* str, char c, usz times) +fn void DString.append_repeat(&self, char c, usz times) { if (times == 0) return; - str.reserve(times); - StringData* data = str.data(); + self.reserve(times); + StringData* data = self.data(); for (usz i = 0; i < times; i++) { data.chars[data.len++] = c; @@ -131,80 +131,80 @@ fn void DString.append_repeat(DString* str, char c, usz times) /** * @require c <= 0x10ffff */ -fn void DString.append_char32(DString* str, Char32 c) +fn void DString.append_char32(&self, Char32 c) { if (c < 0x7f) { - str.reserve(1); - StringData* data = str.data(); + self.reserve(1); + StringData* data = self.data(); data.chars[data.len++] = (char)c; return; } if (c < 0x7ff) { - str.reserve(2); - StringData* data = str.data(); + self.reserve(2); + StringData* data = self.data(); data.chars[data.len++] = (char)(0xC0 | c >> 6); data.chars[data.len++] = (char)(0x80 | (c & 0x3F)); return; } if (c < 0xffff) { - str.reserve(3); - StringData* data = str.data(); + self.reserve(3); + StringData* data = self.data(); data.chars[data.len++] = (char)(0xE0 | c >> 12); data.chars[data.len++] = (char)(0x80 | (c >> 6 & 0x3F)); data.chars[data.len++] = (char)(0x80 | (c & 0x3F)); return; } - str.reserve(4); - StringData* data = str.data(); + self.reserve(4); + StringData* data = self.data(); data.chars[data.len++] = (char)(0xF0 | c >> 18); data.chars[data.len++] = (char)(0x80 | (c >> 12 & 0x3F)); data.chars[data.len++] = (char)(0x80 | (c >> 6 & 0x3F)); data.chars[data.len++] = (char)(0x80 | (c & 0x3F)); } -fn DString DString.tcopy(DString* str) => str.copy(mem::temp()); +fn DString DString.tcopy(&self) => self.copy(mem::temp()); -fn DString DString.copy(DString* str, Allocator* using = null) +fn DString DString.copy(self, Allocator* using = null) { - if (!str) + if (!self) { if (using) return new_with_capacity(0, using); return (DString)null; } if (!using) using = mem::heap(); - StringData* data = str.data(); + StringData* data = self.data(); DString new_string = new_with_capacity(data.capacity, using); mem::copy((char*)new_string.data(), (char*)data, StringData.sizeof + data.len); return new_string; } -fn ZString DString.copy_zstr(DString* str, Allocator* using = mem::heap()) +fn ZString DString.copy_zstr(self, Allocator* using = mem::heap()) { - usz str_len = str.len(); + usz str_len = self.len(); if (!str_len) { return (ZString)calloc(1, .using = using); } char* zstr = malloc(str_len + 1, .using = using); - StringData* data = str.data(); + StringData* data = self.data(); mem::copy(zstr, &data.chars, str_len); zstr[str_len] = 0; return (ZString)zstr; } -fn String DString.copy_str(DString* str, Allocator* using = mem::heap()) +fn String DString.copy_str(self, Allocator* using = mem::heap()) { - return (String)str.copy_zstr(using)[:str.len()]; + return (String)self.copy_zstr(using)[:self.len()]; } -fn String DString.tcopy_str(DString* str) => str.copy_str(mem::temp()) @inline; +fn String DString.tcopy_str(self) => self.copy_str(mem::temp()) @inline; -fn bool DString.equals(DString str, DString other_string) +fn bool DString.equals(self, DString other_string) { - StringData *str1 = str.data(); + StringData *str1 = self.data(); StringData *str2 = other_string.data(); if (str1 == str2) return true; if (!str1) return str2.len == 0; @@ -218,18 +218,18 @@ fn bool DString.equals(DString str, DString other_string) return true; } -fn void DString.free(DString* str) +fn void DString.free(&self) { - if (!*str) return; - StringData* data = str.data(); + if (!*self) return; + StringData* data = self.data(); if (!data) return; free(data, .using = data.allocator); - *str = (DString)null; + *self = (DString)null; } -fn bool DString.less(DString str, DString other_string) +fn bool DString.less(self, DString other_string) { - StringData* str1 = str.data(); + StringData* str1 = self.data(); StringData* str2 = other_string.data(); if (str1 == str2) return false; if (!str1) return str2.len != 0; @@ -244,69 +244,70 @@ fn bool DString.less(DString str, DString other_string) return true; } -fn void DString.append_chars(DString* this, String str) +fn void DString.append_chars(&self, String str) { usz other_len = str.len; if (!other_len) return; - if (!*this) + if (!*self) { - *this = new(str); + *self = new(str); return; } - this.reserve(other_len); - StringData* data = (StringData*)*this; + self.reserve(other_len); + StringData* data = self.data(); mem::copy(&data.chars[data.len], str.ptr, other_len); data.len += other_len; } -fn Char32[] DString.copy_utf32(DString* this, Allocator* using = mem::heap()) +fn Char32[] DString.copy_utf32(&self, Allocator* using = mem::heap()) { - return this.str().to_utf32(using) @inline!!; + return self.str().to_utf32(using) @inline!!; } -fn void DString.append_string(DString* this, DString str) +fn void DString.append_string(&self, DString str) { StringData* other = (StringData*)str; if (!other) return; - this.append(str.str()); + self.append(str.str()); } -fn void DString.clear(DString* str) +fn void DString.clear(self) { - str.data().len = 0; + if (!self) return; + self.data().len = 0; } -fn void DString.append_char(DString* str, char c) +fn void DString.append_char(&self, char c) { - if (!*str) + if (!*self) { - *str = new_with_capacity(MIN_CAPACITY); + *self = new_with_capacity(MIN_CAPACITY); } - str.reserve(1); - StringData* data = (StringData*)*str; + self.reserve(1); + StringData* data = (StringData*)*self; data.chars[data.len++] = c; } -macro void DString.append(DString* str, value) +macro void DString.append(&self, value) { var $Type = $typeof(value); $switch ($Type) $case char: $case ichar: - str.append_char(value); + self.append_char(value); $case DString: - str.append_string(value); + self.append_string(value); $case String: - str.append_chars(value); + self.append_chars(value); $case Char32: - str.append_char32(value); + self.append_char32(value); $default: $switch $case @convertible(value, Char32): - str.append_char32(value); + self.append_char32(value); $case @convertible(value, String): - str.append_chars(value); + self.append_chars(value); $default: $error "Unsupported type for append – use printf instead."; $endswitch @@ -314,19 +315,19 @@ macro void DString.append(DString* str, value) } -fn usz! DString.printf(DString* str, String format, args...) @maydiscard +fn usz! DString.printf(&self, String format, args...) @maydiscard { Formatter formatter; - formatter.init(&out_string_append_fn, str); + formatter.init(&out_string_append_fn, self); return formatter.vprintf(format, args); } -fn usz! DString.printfn(DString* str, String format, args...) @maydiscard +fn usz! DString.printfn(&self, String format, args...) @maydiscard { Formatter formatter; - formatter.init(&out_string_append_fn, str); + formatter.init(&out_string_append_fn, self); usz len = formatter.vprintf(format, args)!; - str.append('\n'); + self.append('\n'); return len + 1; } @@ -355,35 +356,35 @@ fn void! out_string_append_fn(char c, void* data) @private } -fn StringData* DString.data(DString str) @inline @private +fn StringData* DString.data(self) @inline @private { - return (StringData*)str; + return (StringData*)self; } -fn void DString.reserve(DString* str, usz addition) +fn void DString.reserve(&self, usz addition) { - StringData* data = str.data(); + StringData* data = self.data(); if (!data) { - *str = dstring::new_with_capacity(addition); + *self = dstring::new_with_capacity(addition); return; } usz len = data.len + addition; if (data.capacity >= len) return; usz new_capacity = data.capacity *= 2; if (new_capacity < MIN_CAPACITY) new_capacity = MIN_CAPACITY; - *str = (DString)realloc(data, StringData.sizeof + new_capacity, .using = data.allocator); + *self = (DString)realloc(data, StringData.sizeof + new_capacity, .using = data.allocator); } -fn usz! DString.read_from_stream(DString* string, Stream reader) +fn usz! DString.read_from_stream(&self, Stream reader) { if (reader.supports_available()) { usz total_read = 0; while (usz available = reader.available()!) { - string.reserve(available); - StringData* data = string.data(); + self.reserve(available); + StringData* data = self.data(); usz len = reader.read(data.chars[data.len..(data.capacity - 1)])!; total_read += len; data.len += len; @@ -394,8 +395,8 @@ fn usz! DString.read_from_stream(DString* string, Stream reader) while (true) { // Reserve at least 16 bytes - string.reserve(16); - StringData* data = string.data(); + self.reserve(16); + StringData* data = self.data(); // Read into the rest of the buffer usz read = reader.read(data.chars[data.len..(data.capacity - 1)])!; data.len += read; diff --git a/lib/std/core/os/wasm_memory.c3 b/lib/std/core/os/wasm_memory.c3 index fa45ba875..5665452ed 100644 --- a/lib/std/core/os/wasm_memory.c3 +++ b/lib/std/core/os/wasm_memory.c3 @@ -11,22 +11,22 @@ struct WasmMemory uptr use; } -fn char[]! WasmMemory.allocate_block(WasmMemory* this, usz bytes) +fn char[]! WasmMemory.allocate_block(&self, usz bytes) { - if (!this.allocation) + if (!self.allocation) { - this.allocation = $$wasm_memory_size(0) * WASM_BLOCK_SIZE; + self.allocation = $$wasm_memory_size(0) * WASM_BLOCK_SIZE; } - isz bytes_required = bytes + this.use - this.allocation; + isz bytes_required = bytes + self.use - self.allocation; if (bytes_required <= 0) { - defer this.use += bytes; - return ((char*)this.use)[:bytes]; + defer self.use += bytes; + return ((char*)self.use)[:bytes]; } usz blocks_required = (bytes_required + WASM_BLOCK_SIZE + 1) / WASM_BLOCK_SIZE; if ($$wasm_memory_grow(0, blocks_required) == -1) return AllocationFailure.OUT_OF_MEMORY?; - this.allocation = $$wasm_memory_size(0) * WASM_BLOCK_SIZE; - defer this.use += bytes; - return ((char*)this.use)[:bytes]; + self.allocation = $$wasm_memory_size(0) * WASM_BLOCK_SIZE; + defer self.use += bytes; + return ((char*)self.use)[:bytes]; } \ No newline at end of file diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index eb59920fa..2fd017e41 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -413,7 +413,7 @@ fn String! from_zutf16(Char16* utf16_pointer, Allocator* using = mem::heap()) return from_utf16(utf16, using); } -fn usz String.utf8_codepoints(String s) +fn usz String.utf8_codepoints(s) { usz len = 0; foreach (char c : s) @@ -424,7 +424,7 @@ fn usz String.utf8_codepoints(String s) } -macro String.to_integer(String string, $Type) +macro String.to_integer(string, $Type) { usz len = string.len; usz index = 0; @@ -496,19 +496,19 @@ macro String.to_integer(String string, $Type) } -fn Char16[]! String.to_temp_utf16(String s) => s.to_utf16(mem::temp()); +fn Char16[]! String.to_temp_utf16(s) => s.to_utf16(mem::temp()); -fn int128! String.to_int128(String s) => s.to_integer(int128); -fn long! String.to_long(String s) => s.to_integer(long); -fn int! String.to_int(String s) => s.to_integer(int); -fn short! String.to_short(String s) => s.to_integer(short); -fn ichar! String.to_ichar(String s) => s.to_integer(ichar); +fn int128! String.to_int128(s) => s.to_integer(int128); +fn long! String.to_long(s) => s.to_integer(long); +fn int! String.to_int(s) => s.to_integer(int); +fn short! String.to_short(s) => s.to_integer(short); +fn ichar! String.to_ichar(s) => s.to_integer(ichar); -fn uint128! String.to_uint128(String s) => s.to_integer(uint128); -fn ulong! String.to_ulong(String s) => s.to_integer(ulong); -fn uint! String.to_uint(String s) => s.to_integer(uint); -fn ushort! String.to_ushort(String s) => s.to_integer(ushort); -fn char! String.to_uchar(String s) => s.to_integer(char); +fn uint128! String.to_uint128(s) => s.to_integer(uint128); +fn ulong! String.to_ulong(s) => s.to_integer(ulong); +fn uint! String.to_uint(s) => s.to_integer(uint); +fn ushort! String.to_ushort(s) => s.to_integer(ushort); +fn char! String.to_uchar(s) => s.to_integer(char); -fn double! String.to_double(String s) => s.to_real(double); -fn float! String.to_float(String s) => s.to_real(float); +fn double! String.to_double(s) => s.to_real(double); +fn float! String.to_float(s) => s.to_real(float); diff --git a/lib/std/io/os/getcwd.c3 b/lib/std/io/os/getcwd.c3 index c74fb6414..010915cb8 100644 --- a/lib/std/io/os/getcwd.c3 +++ b/lib/std/io/os/getcwd.c3 @@ -36,7 +36,6 @@ macro String! getcwd(Allocator* using = mem::heap()) $default: unreachable("'getcwd' not available"); - return ""; $endswitch } diff --git a/lib/std/io/os/mkdir.c3 b/lib/std/io/os/mkdir.c3 index 3a95ad59c..717e364b8 100644 --- a/lib/std/io/os/mkdir.c3 +++ b/lib/std/io/os/mkdir.c3 @@ -46,6 +46,5 @@ macro bool! native_mkdir(Path path, MkdirPermissions permissions) }; $default: unreachable("'mkdir' not available"); - return false; $endswitch } \ No newline at end of file diff --git a/lib/std/io/os/rmdir.c3 b/lib/std/io/os/rmdir.c3 index 9c8bf5257..911c291ff 100644 --- a/lib/std/io/os/rmdir.c3 +++ b/lib/std/io/os/rmdir.c3 @@ -44,6 +44,5 @@ macro bool! native_rmdir(Path path) }; $default: unreachable("'rmdir' not available"); - return false; $endswitch } diff --git a/lib/std/io/path.c3 b/lib/std/io/path.c3 index 2dc483519..8a20454a7 100644 --- a/lib/std/io/path.c3 +++ b/lib/std/io/path.c3 @@ -129,9 +129,9 @@ fn Path! new_posix(String path, Allocator* using = mem::heap()) return new(path, using, POSIX); } -fn bool Path.equals(Path p1, Path p2) +fn bool Path.equals(self, Path p2) { - return p1.env == p2.env && p1.path_string == p2.path_string; + return self.env == p2.env && self.path_string == p2.path_string; } /** @@ -139,57 +139,57 @@ fn bool Path.equals(Path p1, Path p2) * * @param [in] path * @param [in] filename - * @ensure return.path_string.len >= path.path_string.len + * @ensure return.path_string.len >= self.path_string.len **/ -fn Path! Path.append(Path path, String filename, Allocator* using = mem::heap()) +fn Path! Path.append(self, String filename, Allocator* using = mem::heap()) { - if (!path.path_string.len) return new(filename, using, path.env)!; - assert(!is_separator(path.path_string[^1], path.env)); + if (!self.path_string.len) return new(filename, using, self.env)!; + assert(!is_separator(self.path_string[^1], self.env)); @stack_mem(256; Allocator* mem) { - DString dstr = dstring::new_with_capacity(path.path_string.len + 1 + filename.len, .using = mem); - dstr.append(path.path_string); + DString dstr = dstring::new_with_capacity(self.path_string.len + 1 + filename.len, .using = mem); + dstr.append(self.path_string); dstr.append(PREFERRED_SEPARATOR); dstr.append(filename); - return { normalize(dstr.copy_str(using), path.env), path.env }; + return { normalize(dstr.copy_str(using), self.env), self.env }; }; } -fn Path! Path.tappend(Path path, String filename) => path.append(filename, mem::temp()); +fn Path! Path.tappend(self, String filename) => self.append(filename, mem::temp()); -fn usz Path.start_of_base_name(Path path) @local +fn usz Path.start_of_base_name(self) @local { - String path_str = path.path_string; + String path_str = self.path_string; if (!path_str.len) return 0; - if (path.env == PathEnv.WIN32) + if (self.env == PathEnv.WIN32) { - return path_str.rindex_of(`\`) + 1 ?? volume_name_len(path_str, path.env)!!; + return path_str.rindex_of(`\`) + 1 ?? volume_name_len(path_str, self.env)!!; } return path_str.rindex_of("/") + 1 ?? 0; } -fn String Path.basename(Path path) +fn String Path.basename(self) { - usz basename_start = path.start_of_base_name(); - String path_str = path.path_string; + usz basename_start = self.start_of_base_name(); + String path_str = self.path_string; if (basename_start == path_str.len) return ""; return path_str[basename_start..]; } -fn String Path.dirname(Path path) +fn String Path.dirname(self) { - usz basename_start = path.start_of_base_name(); - String path_str = path.path_string; + usz basename_start = self.start_of_base_name(); + String path_str = self.path_string; if (basename_start == 0) return ""; - usz start = volume_name_len(path_str, path.env)!!; + usz start = volume_name_len(path_str, self.env)!!; if (basename_start <= start + 1) return path_str[:basename_start]; return path_str[:basename_start - 1]; } -fn String! Path.extension(Path path) +fn String! Path.extension(self) { - String basename = path.basename(); + String basename = self.basename(); usz index = basename.rindex_of(".")!; // Plain ".foo" does not have an if (index == 0) return SearchResult.MISSING?; @@ -197,11 +197,11 @@ fn String! Path.extension(Path path) return basename[index + 1..]; } -fn String Path.volume_name(Path path) +fn String Path.volume_name(self) { - usz len = volume_name_len(path.as_str(), path.env)!!; + usz len = volume_name_len(self.as_str(), self.env)!!; if (!len) return ""; - return path.path_string[:len]; + return self.path_string[:len]; } fn usz! volume_name_len(String path, PathEnv path_env) @local @@ -233,14 +233,14 @@ fn usz! volume_name_len(String path, PathEnv path_env) @local } } -fn Path! Path.parent(Path path) +fn Path! Path.parent(self) { - if (path.path_string.len == 1 && is_separator(path.path_string[0], path.env)) return PathResult.NO_PARENT?; - foreach_r(i, c : path.path_string) + if (self.path_string.len == 1 && is_separator(self.path_string[0], self.env)) return PathResult.NO_PARENT?; + foreach_r(i, c : self.path_string) { - if (is_separator(c, path.env)) + if (is_separator(c, self.env)) { - return { path.path_string[:i], path.env }; + return { self.path_string[:i], self.env }; } } return PathResult.NO_PARENT?; @@ -350,16 +350,16 @@ fn String! normalize(String path_str, PathEnv path_env = DEFAULT_PATH_ENV) return path_str[:len]; } -fn ZString Path.as_zstr(Path path) => (ZString)path.path_string.ptr; +fn ZString Path.as_zstr(self) => (ZString)self.path_string.ptr; -fn String Path.root_directory(Path path) +fn String Path.root_directory(self) { - String path_str = path.as_str(); + String path_str = self.as_str(); usz len = path_str.len; if (!len) return ""; - if (path.env == PathEnv.WIN32) + if (self.env == PathEnv.WIN32) { - usz root_len = volume_name_len(path_str, path.env)!!; + usz root_len = volume_name_len(path_str, self.env)!!; if (root_len == len || !is_win32_separator(path_str[root_len])) return ""; return path_str[root_len..root_len]; } @@ -375,21 +375,21 @@ fn String Path.root_directory(Path path) } -fn String Path.as_str(Path path) +fn String Path.as_str(self) { - return path.path_string; + return self.path_string; } -fn bool Path.has_suffix(Path path, String str) +fn bool Path.has_suffix(self, String str) { - return path.as_str().ends_with(str); + return self.as_str().ends_with(str); } -fn void Path.free(Path path) +fn void Path.free(self) { - free(path.path_string.ptr); + free(self.path_string.ptr); } diff --git a/lib/std/math/math.complex.c3 b/lib/std/math/math.complex.c3 index 7d51ad3bc..af6a6e8b3 100644 --- a/lib/std/math/math.complex.c3 +++ b/lib/std/math/math.complex.c3 @@ -11,14 +11,14 @@ union Complex macro Complex identity() => { 1, 0 }; -macro Complex Complex.add(Complex a, Complex b) => Complex { .v = a.v + b.v }; -macro Complex Complex.add_each(Complex a, Real b) => Complex { .v = a.v + b }; -macro Complex Complex.sub(Complex a, Complex b) => Complex { .v = a.v - b.v }; -macro Complex Complex.sub_each(Complex a, Real b) => Complex { .v = a.v - b }; -macro Complex Complex.scale(Complex a, Real s) => Complex { .v = a.v * s }; -macro Complex Complex.mul(Complex a, Complex b) => { a.r * b.r - a.c * b.c, a.r * b.c + b.r * a.c }; -macro Complex Complex.div(Complex a, Complex b) +macro Complex Complex.add(self, Complex b) => Complex { .v = self.v + b.v }; +macro Complex Complex.add_each(self, Real b) => Complex { .v = self.v + b }; +macro Complex Complex.sub(self, Complex b) => Complex { .v = self.v - b.v }; +macro Complex Complex.sub_each(self, Real b) => Complex { .v = self.v - b }; +macro Complex Complex.scale(self, Real s) => Complex { .v = self.v * s }; +macro Complex Complex.mul(self, Complex b) => { self.r * b.r - self.c * b.c, self.r * b.c + b.r * self.c }; +macro Complex Complex.div(self, Complex b) { Real div = b.v.dot(b.v); - return Complex{ (a.r * b.r + a.c * b.c) / div, (a.c * b.r - a.r * b.c) / div }; + return Complex{ (self.r * b.r + self.c * b.c) / div, (self.c * b.r - self.r * b.c) / div }; } diff --git a/lib/std/math/math.matrix.c3 b/lib/std/math/math.matrix.c3 index 7a9694184..40840d8ff 100644 --- a/lib/std/math/math.matrix.c3 +++ b/lib/std/math/math.matrix.c3 @@ -42,62 +42,62 @@ struct Matrix4x4 } } -fn Real[<2>] Matrix2x2.apply(Matrix2x2* mat, Real[<2>] vec) +fn Real[<2>] Matrix2x2.apply(&self, Real[<2>] vec) { - return Real[<2>] { - mat.m00 * vec[0] + mat.m01 * vec[1], - mat.m10 * vec[0] + mat.m11 * vec[1], + return { + self.m00 * vec[0] + self.m01 * vec[1], + self.m10 * vec[0] + self.m11 * vec[1], }; } -fn Real[<3>] Matrix3x3.apply(Matrix3x3* mat, Real[<3>] vec) +fn Real[<3>] Matrix3x3.apply(&self, Real[<3>] vec) { - return Real[<3>] { - mat.m00 * vec[0] + mat.m01 * vec[1] + mat.m02 * vec[2], - mat.m10 * vec[0] + mat.m11 * vec[1] + mat.m12 * vec[2], - mat.m20 * vec[0] + mat.m21 * vec[1] + mat.m22 * vec[2], + return { + self.m00 * vec[0] + self.m01 * vec[1] + self.m02 * vec[2], + self.m10 * vec[0] + self.m11 * vec[1] + self.m12 * vec[2], + self.m20 * vec[0] + self.m21 * vec[1] + self.m22 * vec[2], }; } -fn Real[<4>] Matrix4x4.apply(Matrix4x4* mat, Real[<4>] vec) +fn Real[<4>] Matrix4x4.apply(&self, Real[<4>] vec) { - return Real[<4>] { - mat.m00 * vec[0] + mat.m01 * vec[1] + mat.m02 * vec[2] + mat.m03 * vec[3], - mat.m10 * vec[0] + mat.m11 * vec[1] + mat.m12 * vec[2] + mat.m13 * vec[3], - mat.m20 * vec[0] + mat.m21 * vec[1] + mat.m22 * vec[2] + mat.m23 * vec[3], - mat.m30 * vec[0] + mat.m31 * vec[1] + mat.m32 * vec[2] + mat.m33 * vec[3], + return { + self.m00 * vec[0] + self.m01 * vec[1] + self.m02 * vec[2] + self.m03 * vec[3], + self.m10 * vec[0] + self.m11 * vec[1] + self.m12 * vec[2] + self.m13 * vec[3], + self.m20 * vec[0] + self.m21 * vec[1] + self.m22 * vec[2] + self.m23 * vec[3], + self.m30 * vec[0] + self.m31 * vec[1] + self.m32 * vec[2] + self.m33 * vec[3], }; } -fn Matrix2x2 Matrix2x2.mul(Matrix2x2* a, Matrix2x2 b) +fn Matrix2x2 Matrix2x2.mul(&self, Matrix2x2 b) { - return Matrix2x2 { - a.m00 * b.m00 + a.m01 * b.m10, a.m00 * b.m01 + a.m01 * b.m11, - a.m10 * b.m00 + a.m11 * b.m10, a.m10 * b.m01 + a.m11 * b.m11, + return { + self.m00 * b.m00 + self.m01 * b.m10, self.m00 * b.m01 + self.m01 * b.m11, + self.m10 * b.m00 + self.m11 * b.m10, self.m10 * b.m01 + self.m11 * b.m11, }; } -fn Matrix3x3 Matrix3x3.mul(Matrix3x3* a, Matrix3x3 b) +fn Matrix3x3 Matrix3x3.mul(&self, Matrix3x3 b) { - return Matrix3x3 { - a.m00 * b.m00 + a.m01 * b.m10 + a.m02 * b.m20, - a.m00 * b.m01 + a.m01 * b.m11 + a.m02 * b.m21, - a.m00 * b.m02 + a.m01 * b.m12 + a.m02 * b.m22, + return { + self.m00 * b.m00 + self.m01 * b.m10 + self.m02 * b.m20, + self.m00 * b.m01 + self.m01 * b.m11 + self.m02 * b.m21, + self.m00 * b.m02 + self.m01 * b.m12 + self.m02 * b.m22, - a.m10 * b.m00 + a.m11 * b.m10 + a.m12 * b.m20, - a.m10 * b.m01 + a.m11 * b.m11 + a.m12 * b.m21, - a.m10 * b.m02 + a.m11 * b.m12 + a.m12 * b.m22, + self.m10 * b.m00 + self.m11 * b.m10 + self.m12 * b.m20, + self.m10 * b.m01 + self.m11 * b.m11 + self.m12 * b.m21, + self.m10 * b.m02 + self.m11 * b.m12 + self.m12 * b.m22, - a.m20 * b.m00 + a.m21 * b.m10 + a.m22 * b.m20, - a.m20 * b.m01 + a.m21 * b.m11 + a.m22 * b.m21, - a.m20 * b.m02 + a.m21 * b.m12 + a.m22 * b.m22, + self.m20 * b.m00 + self.m21 * b.m10 + self.m22 * b.m20, + self.m20 * b.m01 + self.m21 * b.m11 + self.m22 * b.m21, + self.m20 * b.m02 + self.m21 * b.m12 + self.m22 * b.m22, }; } fn Matrix4x4 Matrix4x4.mul(Matrix4x4* a, Matrix4x4 b) { - return Matrix4x4 { + return { a.m00 * b.m00 + a.m01 * b.m10 + a.m02 * b.m20 + a.m03 * b.m30, a.m00 * b.m01 + a.m01 * b.m11 + a.m02 * b.m21 + a.m03 * b.m31, a.m00 * b.m02 + a.m01 * b.m12 + a.m02 * b.m22 + a.m03 * b.m32, @@ -120,196 +120,196 @@ fn Matrix4x4 Matrix4x4.mul(Matrix4x4* a, Matrix4x4 b) }; } -fn Matrix2x2 Matrix2x2.component_mul(Matrix2x2* mat, Real s) => matrix_component_mul(mat, s); -fn Matrix3x3 Matrix3x3.component_mul(Matrix3x3* mat, Real s) => matrix_component_mul(mat, s); -fn Matrix4x4 Matrix4x4.component_mul(Matrix4x4* mat, Real s) => matrix_component_mul(mat, s); +fn Matrix2x2 Matrix2x2.component_mul(&self, Real s) => matrix_component_mul(self, s); +fn Matrix3x3 Matrix3x3.component_mul(&self, Real s) => matrix_component_mul(self, s); +fn Matrix4x4 Matrix4x4.component_mul(&self, Real s) => matrix_component_mul(self, s); -fn Matrix2x2 Matrix2x2.add(Matrix2x2* mat, Matrix2x2 mat2) => matrix_add(mat, mat2); -fn Matrix3x3 Matrix3x3.add(Matrix3x3* mat, Matrix3x3 mat2) => matrix_add(mat, mat2); -fn Matrix4x4 Matrix4x4.add(Matrix4x4* mat, Matrix4x4 mat2) => matrix_add(mat, mat2); +fn Matrix2x2 Matrix2x2.add(&self, Matrix2x2 mat2) => matrix_add(self, mat2); +fn Matrix3x3 Matrix3x3.add(&self, Matrix3x3 mat2) => matrix_add(self, mat2); +fn Matrix4x4 Matrix4x4.add(&self, Matrix4x4 mat2) => matrix_add(self, mat2); -fn Matrix2x2 Matrix2x2.sub(Matrix2x2* mat, Matrix2x2 mat2) => matrix_sub(mat, mat2); -fn Matrix3x3 Matrix3x3.sub(Matrix3x3* mat, Matrix3x3 mat2) => matrix_sub(mat, mat2); -fn Matrix4x4 Matrix4x4.sub(Matrix4x4* mat, Matrix4x4 mat2) => matrix_sub(mat, mat2); +fn Matrix2x2 Matrix2x2.sub(&self, Matrix2x2 mat2) => matrix_sub(self, mat2); +fn Matrix3x3 Matrix3x3.sub(&self, Matrix3x3 mat2) => matrix_sub(self, mat2); +fn Matrix4x4 Matrix4x4.sub(&self, Matrix4x4 mat2) => matrix_sub(self, mat2); -fn Matrix2x2 Matrix2x2.transpose(Matrix2x2* mat) +fn Matrix2x2 Matrix2x2.transpose(&self) { - return Matrix2x2 { - mat.m00, mat.m10, - mat.m01, mat.m11 + return { + self.m00, self.m10, + self.m01, self.m11 }; } -fn Matrix3x3 Matrix3x3.transpose(Matrix3x3* mat) +fn Matrix3x3 Matrix3x3.transpose(&self) { - return Matrix3x3 { - mat.m00, mat.m10, mat.m20, - mat.m01, mat.m11, mat.m21, - mat.m02, mat.m12, mat.m22, + return { + self.m00, self.m10, self.m20, + self.m01, self.m11, self.m21, + self.m02, self.m12, self.m22, }; } -fn Matrix4x4 Matrix4x4.transpose(Matrix4x4* mat) +fn Matrix4x4 Matrix4x4.transpose(&self) { - return Matrix4x4 { - mat.m00, mat.m10, mat.m20, mat.m30, - mat.m01, mat.m11, mat.m21, mat.m31, - mat.m02, mat.m12, mat.m22, mat.m32, - mat.m03, mat.m13, mat.m23, mat.m33, + return { + self.m00, self.m10, self.m20, self.m30, + self.m01, self.m11, self.m21, self.m31, + self.m02, self.m12, self.m22, self.m32, + self.m03, self.m13, self.m23, self.m33, }; } -fn Real Matrix2x2.determinant(Matrix2x2* mat) +fn Real Matrix2x2.determinant(&self) { - return mat.m00 * mat.m11 - mat.m01 * mat.m10; + return self.m00 * self.m11 - self.m01 * self.m10; } -fn Real Matrix3x3.determinant(Matrix3x3* mat) +fn Real Matrix3x3.determinant(&self) { return - mat.m00 * (mat.m11 * mat.m22 - mat.m21 * mat.m12) - - mat.m01 * (mat.m10 * mat.m22 - mat.m20 * mat.m12) + - mat.m02 * (mat.m10 * mat.m21 - mat.m20 * mat.m11); + self.m00 * (self.m11 * self.m22 - self.m21 * self.m12) - + self.m01 * (self.m10 * self.m22 - self.m20 * self.m12) + + self.m02 * (self.m10 * self.m21 - self.m20 * self.m11); } -fn Real Matrix4x4.determinant(Matrix4x4* mat) +fn Real Matrix4x4.determinant(&self) { return - mat.m00 * (mat.m11 * (mat.m22 * mat.m33 - mat.m32 * mat.m23) - - mat.m12 * (mat.m21 * mat.m33 - mat.m31 * mat.m23) + - mat.m13 * (mat.m21 * mat.m32 - mat.m31 * mat.m22) ) - - mat.m01 * (mat.m10 * (mat.m22 * mat.m33 - mat.m32 * mat.m23) - - mat.m12 * (mat.m20 * mat.m33 - mat.m30 * mat.m23) + - mat.m13 * (mat.m20 * mat.m32 - mat.m30 * mat.m22) ) + - mat.m02 * (mat.m10 * (mat.m21 * mat.m33 - mat.m31 * mat.m23) - - mat.m11 * (mat.m20 * mat.m33 - mat.m30 * mat.m23) + - mat.m13 * (mat.m20 * mat.m31 - mat.m30 * mat.m21) ) - - mat.m03 * (mat.m10 * (mat.m21 * mat.m32 - mat.m31 * mat.m22) - - mat.m11 * (mat.m20 * mat.m32 - mat.m30 * mat.m22) + - mat.m12 * (mat.m20 * mat.m31 - mat.m30 * mat.m21) ); + self.m00 * (self.m11 * (self.m22 * self.m33 - self.m32 * self.m23) - + self.m12 * (self.m21 * self.m33 - self.m31 * self.m23) + + self.m13 * (self.m21 * self.m32 - self.m31 * self.m22) ) - + self.m01 * (self.m10 * (self.m22 * self.m33 - self.m32 * self.m23) - + self.m12 * (self.m20 * self.m33 - self.m30 * self.m23) + + self.m13 * (self.m20 * self.m32 - self.m30 * self.m22) ) + + self.m02 * (self.m10 * (self.m21 * self.m33 - self.m31 * self.m23) - + self.m11 * (self.m20 * self.m33 - self.m30 * self.m23) + + self.m13 * (self.m20 * self.m31 - self.m30 * self.m21) ) - + self.m03 * (self.m10 * (self.m21 * self.m32 - self.m31 * self.m22) - + self.m11 * (self.m20 * self.m32 - self.m30 * self.m22) + + self.m12 * (self.m20 * self.m31 - self.m30 * self.m21) ); } -fn Matrix2x2 Matrix2x2.adjoint(Matrix2x2* mat) +fn Matrix2x2 Matrix2x2.adjoint(&self) { - return Matrix2x2 { mat.m00, -mat.m01, -mat.m10, mat.m11 }; + return { self.m00, -self.m01, -self.m10, self.m11 }; } -fn Matrix3x3 Matrix3x3.adjoint(Matrix3x3* mat) +fn Matrix3x3 Matrix3x3.adjoint(&self) { - return Matrix3x3 { - (mat.m11 * mat.m22 - mat.m21 * mat.m12), - -(mat.m10 * mat.m22 - mat.m20 * mat.m12), - (mat.m10 * mat.m21 - mat.m20 * mat.m11), + return { + (self.m11 * self.m22 - self.m21 * self.m12), + -(self.m10 * self.m22 - self.m20 * self.m12), + (self.m10 * self.m21 - self.m20 * self.m11), - -(mat.m01 * mat.m22 - mat.m21 * mat.m02), - (mat.m00 * mat.m22 - mat.m20 * mat.m02), - -(mat.m00 * mat.m21 - mat.m20 * mat.m01), + -(self.m01 * self.m22 - self.m21 * self.m02), + (self.m00 * self.m22 - self.m20 * self.m02), + -(self.m00 * self.m21 - self.m20 * self.m01), - (mat.m01 * mat.m12 - mat.m11 * mat.m02), - -(mat.m00 * mat.m12 - mat.m10 * mat.m02), - (mat.m00 * mat.m11 - mat.m10 * mat.m01), + (self.m01 * self.m12 - self.m11 * self.m02), + -(self.m00 * self.m12 - self.m10 * self.m02), + (self.m00 * self.m11 - self.m10 * self.m01), }; } -fn Matrix4x4 Matrix4x4.adjoint(Matrix4x4* mat) +fn Matrix4x4 Matrix4x4.adjoint(&self) { - return Matrix4x4 { - (mat.m11 * (mat.m22 * mat.m33 - mat.m32 * mat.m23) - - mat.m12 * (mat.m21 * mat.m33 - mat.m31 * mat.m23) + - mat.m13 * (mat.m21 * mat.m32 - mat.m31 * mat.m22)), - -(mat.m10 * (mat.m22 * mat.m33 - mat.m32 * mat.m23) - - mat.m12 * (mat.m20 * mat.m33 - mat.m30 * mat.m23) + - mat.m13 * (mat.m20 * mat.m32 - mat.m30 * mat.m22)), - (mat.m10 * (mat.m21 * mat.m33 - mat.m31 * mat.m23) - - mat.m11 * (mat.m20 * mat.m33 - mat.m30 * mat.m23) + - mat.m13 * (mat.m20 * mat.m31 - mat.m30 * mat.m21)), - -(mat.m10 * (mat.m21 * mat.m32 - mat.m31 * mat.m22) - - mat.m11 * (mat.m20 * mat.m32 - mat.m30 * mat.m22) + - mat.m12 * (mat.m20 * mat.m31 - mat.m30 * mat.m21)), + return { + (self.m11 * (self.m22 * self.m33 - self.m32 * self.m23) - + self.m12 * (self.m21 * self.m33 - self.m31 * self.m23) + + self.m13 * (self.m21 * self.m32 - self.m31 * self.m22)), + -(self.m10 * (self.m22 * self.m33 - self.m32 * self.m23) - + self.m12 * (self.m20 * self.m33 - self.m30 * self.m23) + + self.m13 * (self.m20 * self.m32 - self.m30 * self.m22)), + (self.m10 * (self.m21 * self.m33 - self.m31 * self.m23) - + self.m11 * (self.m20 * self.m33 - self.m30 * self.m23) + + self.m13 * (self.m20 * self.m31 - self.m30 * self.m21)), + -(self.m10 * (self.m21 * self.m32 - self.m31 * self.m22) - + self.m11 * (self.m20 * self.m32 - self.m30 * self.m22) + + self.m12 * (self.m20 * self.m31 - self.m30 * self.m21)), - -(mat.m01 * (mat.m22 * mat.m33 - mat.m32 * mat.m23) - - mat.m02 * (mat.m21 * mat.m33 - mat.m31 * mat.m23) + - mat.m03 * (mat.m21 * mat.m32 - mat.m31 * mat.m22)), - (mat.m00 * (mat.m22 * mat.m33 - mat.m32 * mat.m23) - - mat.m02 * (mat.m20 * mat.m33 - mat.m30 * mat.m23) + - mat.m03 * (mat.m20 * mat.m32 - mat.m30 * mat.m22)), - -(mat.m00 * (mat.m21 * mat.m33 - mat.m31 * mat.m23) - - mat.m01 * (mat.m20 * mat.m33 - mat.m30 * mat.m23) + - mat.m03 * (mat.m20 * mat.m31 - mat.m30 * mat.m21)), - (mat.m00 * (mat.m21 * mat.m32 - mat.m31 * mat.m22) - - mat.m01 * (mat.m20 * mat.m32 - mat.m30 * mat.m22) + - mat.m02 * (mat.m20 * mat.m31 - mat.m30 * mat.m21)), + -(self.m01 * (self.m22 * self.m33 - self.m32 * self.m23) - + self.m02 * (self.m21 * self.m33 - self.m31 * self.m23) + + self.m03 * (self.m21 * self.m32 - self.m31 * self.m22)), + (self.m00 * (self.m22 * self.m33 - self.m32 * self.m23) - + self.m02 * (self.m20 * self.m33 - self.m30 * self.m23) + + self.m03 * (self.m20 * self.m32 - self.m30 * self.m22)), + -(self.m00 * (self.m21 * self.m33 - self.m31 * self.m23) - + self.m01 * (self.m20 * self.m33 - self.m30 * self.m23) + + self.m03 * (self.m20 * self.m31 - self.m30 * self.m21)), + (self.m00 * (self.m21 * self.m32 - self.m31 * self.m22) - + self.m01 * (self.m20 * self.m32 - self.m30 * self.m22) + + self.m02 * (self.m20 * self.m31 - self.m30 * self.m21)), - (mat.m01 * (mat.m12 * mat.m33 - mat.m32 * mat.m13) - - mat.m02 * (mat.m11 * mat.m33 - mat.m31 * mat.m13) + - mat.m03 * (mat.m11 * mat.m32 - mat.m31 * mat.m12)), - -(mat.m00 * (mat.m12 * mat.m33 - mat.m32 * mat.m13) - - mat.m02 * (mat.m10 * mat.m33 - mat.m30 * mat.m13) + - mat.m03 * (mat.m10 * mat.m32 - mat.m30 * mat.m12)), - (mat.m00 * (mat.m11 * mat.m33 - mat.m31 * mat.m13) - - mat.m01 * (mat.m10 * mat.m33 - mat.m30 * mat.m13) + - mat.m03 * (mat.m10 * mat.m31 - mat.m30 * mat.m11)), - -(mat.m00 * (mat.m11 * mat.m32 - mat.m31 * mat.m12) - - mat.m01 * (mat.m10 * mat.m32 - mat.m30 * mat.m12) + - mat.m02 * (mat.m10 * mat.m31 - mat.m30 * mat.m11)), + (self.m01 * (self.m12 * self.m33 - self.m32 * self.m13) - + self.m02 * (self.m11 * self.m33 - self.m31 * self.m13) + + self.m03 * (self.m11 * self.m32 - self.m31 * self.m12)), + -(self.m00 * (self.m12 * self.m33 - self.m32 * self.m13) - + self.m02 * (self.m10 * self.m33 - self.m30 * self.m13) + + self.m03 * (self.m10 * self.m32 - self.m30 * self.m12)), + (self.m00 * (self.m11 * self.m33 - self.m31 * self.m13) - + self.m01 * (self.m10 * self.m33 - self.m30 * self.m13) + + self.m03 * (self.m10 * self.m31 - self.m30 * self.m11)), + -(self.m00 * (self.m11 * self.m32 - self.m31 * self.m12) - + self.m01 * (self.m10 * self.m32 - self.m30 * self.m12) + + self.m02 * (self.m10 * self.m31 - self.m30 * self.m11)), - -(mat.m01 * (mat.m12 * mat.m23 - mat.m22 * mat.m13) - - mat.m02 * (mat.m11 * mat.m23 - mat.m21 * mat.m13) + - mat.m03 * (mat.m11 * mat.m22 - mat.m21 * mat.m12)), - (mat.m00 * (mat.m12 * mat.m23 - mat.m22 * mat.m13) - - mat.m02 * (mat.m10 * mat.m23 - mat.m20 * mat.m13) + - mat.m03 * (mat.m10 * mat.m22 - mat.m20 * mat.m12)), - -(mat.m00 * (mat.m11 * mat.m23 - mat.m21 * mat.m13) - - mat.m01 * (mat.m10 * mat.m23 - mat.m20 * mat.m13) + - mat.m03 * (mat.m10 * mat.m21 - mat.m20 * mat.m11)), - (mat.m00 * (mat.m11 * mat.m22 - mat.m21 * mat.m12) - - mat.m01 * (mat.m10 * mat.m22 - mat.m20 * mat.m12) + - mat.m02 * (mat.m10 * mat.m21 - mat.m20 * mat.m11)), + -(self.m01 * (self.m12 * self.m23 - self.m22 * self.m13) - + self.m02 * (self.m11 * self.m23 - self.m21 * self.m13) + + self.m03 * (self.m11 * self.m22 - self.m21 * self.m12)), + (self.m00 * (self.m12 * self.m23 - self.m22 * self.m13) - + self.m02 * (self.m10 * self.m23 - self.m20 * self.m13) + + self.m03 * (self.m10 * self.m22 - self.m20 * self.m12)), + -(self.m00 * (self.m11 * self.m23 - self.m21 * self.m13) - + self.m01 * (self.m10 * self.m23 - self.m20 * self.m13) + + self.m03 * (self.m10 * self.m21 - self.m20 * self.m11)), + (self.m00 * (self.m11 * self.m22 - self.m21 * self.m12) - + self.m01 * (self.m10 * self.m22 - self.m20 * self.m12) + + self.m02 * (self.m10 * self.m21 - self.m20 * self.m11)), }; } -fn Matrix2x2! Matrix2x2.inverse(Matrix2x2* m) +fn Matrix2x2! Matrix2x2.inverse(&self) { - Real det = m.determinant(); + Real det = self.determinant(); if (det == 0) return MatrixError.MATRIX_INVERSE_DOESNT_EXIST?; - Matrix2x2 adj = m.adjoint(); + Matrix2x2 adj = self.adjoint(); return adj.component_mul(1 / det).transpose(); } -fn Matrix3x3! Matrix3x3.inverse(Matrix3x3* m) +fn Matrix3x3! Matrix3x3.inverse(&self) { - Real det = m.determinant(); + Real det = self.determinant(); if (det == 0) return MatrixError.MATRIX_INVERSE_DOESNT_EXIST?; - Matrix3x3 adj = m.adjoint(); + Matrix3x3 adj = self.adjoint(); return adj.component_mul(1 / det).transpose(); } -fn Matrix4x4! Matrix4x4.inverse(Matrix4x4* m) +fn Matrix4x4! Matrix4x4.inverse(&self) { - Real det = m.determinant(); + Real det = self.determinant(); if (det == 0) return MatrixError.MATRIX_INVERSE_DOESNT_EXIST?; - Matrix4x4 adj = m.adjoint(); + Matrix4x4 adj = self.adjoint(); return adj.component_mul(1 / det).transpose(); } -fn Matrix3x3 Matrix3x3.translate(Matrix3x3* m, Real[<2>] v) +fn Matrix3x3 Matrix3x3.translate(&self, Real[<2>] v) { - return m.mul(Matrix3x3 { + return self.mul({ 1, 0, v[0], 0, 1, v[1], 0, 0, 1, }); } -fn Matrix4x4 Matrix4x4.translate(Matrix4x4* m, Real[<3>] v) +fn Matrix4x4 Matrix4x4.translate(&self, Real[<3>] v) { - return m.mul(Matrix4x4 { + return self.mul({ 1, 0, 0, v[0], 0, 1, 0, v[1], 0, 0, 1, v[2], @@ -318,9 +318,9 @@ fn Matrix4x4 Matrix4x4.translate(Matrix4x4* m, Real[<3>] v) } // r in radians -fn Matrix3x3 Matrix3x3.rotate(Matrix3x3* m, Real r) +fn Matrix3x3 Matrix3x3.rotate(&self, Real r) { - return m.mul(Matrix3x3 { + return self.mul({ math::cos(r), -math::sin(r), 0, math::sin(r), math::cos(r), 0, 0, 0, 1, @@ -328,9 +328,9 @@ fn Matrix3x3 Matrix3x3.rotate(Matrix3x3* m, Real r) } // r in radians -fn Matrix4x4 Matrix4x4.rotate_z(Matrix4x4* m, Real r) +fn Matrix4x4 Matrix4x4.rotate_z(&self, Real r) { - return m.mul(Matrix4x4 { + return self.mul({ math::cos(r), -math::sin(r), 0, 0, math::sin(r), math::cos(r), 0, 0, 0, 0, 1, 0, @@ -339,9 +339,9 @@ fn Matrix4x4 Matrix4x4.rotate_z(Matrix4x4* m, Real r) } // r in radians -fn Matrix4x4 Matrix4x4.rotate_y(Matrix4x4* m, Real r) +fn Matrix4x4 Matrix4x4.rotate_y(&self, Real r) { - return m.mul(Matrix4x4 { + return self.mul({ math::cos(r), 0, -math::sin(r), 0, 0, 1, 0, 0, math::sin(r), 0, math::cos(r), 0, @@ -350,9 +350,9 @@ fn Matrix4x4 Matrix4x4.rotate_y(Matrix4x4* m, Real r) } // r in radians -fn Matrix4x4 Matrix4x4.rotate_x(Matrix4x4* m, Real r) +fn Matrix4x4 Matrix4x4.rotate_x(&self, Real r) { - return m.mul(Matrix4x4 { + return self.mul({ 1, 0, 0, 0, 0, math::cos(r), -math::sin(r), 0, 0, math::sin(r), math::cos(r), 0, @@ -361,22 +361,22 @@ fn Matrix4x4 Matrix4x4.rotate_x(Matrix4x4* m, Real r) } -fn Matrix3x3 Matrix3x3.scale(Matrix3x3* m, Real[<2>] v) +fn Matrix3x3 Matrix3x3.scale(&self, Real[<2>] v) { - return m.mul(Matrix3x3 { + return self.mul({ v[0], 0, 0, 0, v[1], 0, 0, 0, 1, }); } -fn Real Matrix2x2.trace(Matrix2x2* m) => m.m00 + m.m11; -fn Real Matrix3x3.trace(Matrix3x3* m) => m.m00 + m.m11 + m.m22; -fn Real Matrix4x4.trace(Matrix4x4* m) => m.m00 + m.m11 + m.m22 + m.m33; +fn Real Matrix2x2.trace(&self) => self.m00 + self.m11; +fn Real Matrix3x3.trace(&self) => self.m00 + self.m11 + self.m22; +fn Real Matrix4x4.trace(&self) => self.m00 + self.m11 + self.m22 + self.m33; -fn Matrix4x4 Matrix4x4.scale(Matrix4x4* m, Real[<3>] v) +fn Matrix4x4 Matrix4x4.scale(&self, Real[<3>] v) { - return m.mul(Matrix4x4 { + return self.mul({ v[0], 0, 0, 0, 0, v[1], 0, 0, 0, 0, v[2], 0, @@ -389,7 +389,7 @@ fn Matrix4x4 ortho(Real left, Real right, Real top, Real bottom, Real near, Real Real width = right - left; Real height = top - bottom; Real depth = far - near; - return Matrix4x4 { + return { 2 / width, 0, 0, 0, 0, 2 / height, 0, 0, 0, 0, -2 / depth, 0, @@ -403,7 +403,7 @@ fn Matrix4x4 perspective(Real fov, Real aspect_ratio, Real near, Real far) Real f = (Real)math::tan(math::PI * 0.5 - 0.5 * fov); Real rangeInv = (Real)1.0 / (near - far); - return Matrix4x4 { + return { f / aspect_ratio, 0, 0, 0, 0, f, 0, 0, 0, 0, (near + far) * rangeInv, -1, diff --git a/lib/std/math/math_vector.c3 b/lib/std/math/math_vector.c3 index cb273a029..7e0c3fe64 100644 --- a/lib/std/math/math_vector.c3 +++ b/lib/std/math/math_vector.c3 @@ -9,59 +9,59 @@ def Vec2 = double[<2>]; def Vec3 = double[<3>]; def Vec4 = double[<4>]; -macro Vec2f.length_sq(Vec2f v) => v.dot(v); -macro Vec3f.length_sq(Vec3f v) => v.dot(v); -macro Vec4f.length_sq(Vec4f v) => v.dot(v); -macro Vec2.length_sq(Vec2 v) => v.dot(v); -macro Vec3.length_sq(Vec3 v) => v.dot(v); -macro Vec4.length_sq(Vec4 v) => v.dot(v); +macro Vec2f.length_sq(&self) => self.dot(self); +macro Vec3f.length_sq(&self) => self.dot(self); +macro Vec4f.length_sq(&self) => self.dot(self); +macro Vec2.length_sq(&self) => self.dot(self); +macro Vec3.length_sq(self) => self.dot(self); +macro Vec4.length_sq(self) => self.dot(self); -macro Vec2f.distance_sq(Vec2f v1, Vec2f v2) => (v1 - v2).length_sq(); -macro Vec3f.distance_sq(Vec3f v1, Vec3f v2) => (v1 - v2).length_sq(); -macro Vec4f.distance_sq(Vec4f v1, Vec4f v2) => (v1 - v2).length_sq(); -macro Vec2.distance_sq(Vec2 v1, Vec2 v2) => (v1 - v2).length_sq(); -macro Vec3.distance_sq(Vec3 v1, Vec3 v2) => (v1 - v2).length_sq(); -macro Vec4.distance_sq(Vec4 v1, Vec4 v2) => (v1 - v2).length_sq(); +macro Vec2f.distance_sq(self, Vec2f v2) => (self - v2).length_sq(); +macro Vec3f.distance_sq(self, Vec3f v2) => (self - v2).length_sq(); +macro Vec4f.distance_sq(self, Vec4f v2) => (self - v2).length_sq(); +macro Vec2.distance_sq(self, Vec2 v2) => (self - v2).length_sq(); +macro Vec3.distance_sq(self, Vec3 v2) => (self - v2).length_sq(); +macro Vec4.distance_sq(self, Vec4 v2) => (self - v2).length_sq(); -macro Vec2f.transform(Vec2f v, Matrix4f mat) => transform2(v, mat); -macro Vec2f.rotate(Vec2f v, float angle) => rotate(v, angle); -macro Vec2f.angle(Vec2f v1, Vec2f v2) => math::atan2(v2[1], v2[0]) - math::atan2(v1[1], v2[0]); +macro Vec2f.transform(self, Matrix4f mat) => transform2(self, mat); +macro Vec2f.rotate(self, float angle) => rotate(self, angle); +macro Vec2f.angle(self, Vec2f v2) => math::atan2(v2[1], v2[0]) - math::atan2(self[1], v2[0]); -macro Vec2.transform(Vec2 v, Matrix4 mat) => transform2(v, mat); -macro Vec2.rotate(Vec2 v, double angle) => rotate(v, angle); -macro Vec2.angle(Vec2 v1, Vec2 v2) => math::atan2(v2[1], v2[0]) - math::atan2(v1[1], v2[0]); +macro Vec2.transform(self, Matrix4 mat) => transform2(self, mat); +macro Vec2.rotate(self, double angle) => rotate(self, angle); +macro Vec2.angle(self, Vec2 v2) => math::atan2(v2[1], v2[0]) - math::atan2(self[1], v2[0]); -macro Vec2f.clamp_mag(Vec2f v, float min, float max) => clamp_magnitude(v, min, max); -macro Vec3f.clamp_mag(Vec3f v, float min, float max) => clamp_magnitude(v, min, max); -macro Vec4f.clamp_mag(Vec4f v, float min, float max) => clamp_magnitude(v, min, max); -macro Vec2.clamp_mag(Vec2 v, double min, double max) => clamp_magnitude(v, min, max); -macro Vec3.clamp_mag(Vec3 v, double min, double max) => clamp_magnitude(v, min, max); -macro Vec4.clamp_mag(Vec4 v, double min, double max) => clamp_magnitude(v, min, max); +macro Vec2f.clamp_mag(self, float min, float max) => clamp_magnitude(self, min, max); +macro Vec3f.clamp_mag(self, float min, float max) => clamp_magnitude(self, min, max); +macro Vec4f.clamp_mag(self, float min, float max) => clamp_magnitude(self, min, max); +macro Vec2.clamp_mag(self, double min, double max) => clamp_magnitude(self, min, max); +macro Vec3.clamp_mag(self, double min, double max) => clamp_magnitude(self, min, max); +macro Vec4.clamp_mag(self, double min, double max) => clamp_magnitude(self, min, max); -fn Vec2f Vec2f.towards(Vec2f v, Vec2f target, float max_distance) => towards(v, target, max_distance); -fn Vec3f Vec3f.towards(Vec3f v, Vec3f target, float max_distance) => towards(v, target, max_distance); -fn Vec4f Vec4f.towards(Vec4f v, Vec4f target, float max_distance) => towards(v, target, max_distance); -fn Vec2 Vec2.towards(Vec2 v, Vec2 target, double max_distance) => towards(v, target, max_distance); -fn Vec3 Vec3.towards(Vec3 v, Vec3 target, double max_distance) => towards(v, target, max_distance); -fn Vec4 Vec4.towards(Vec4 v, Vec4 target, double max_distance) => towards(v, target, max_distance); +fn Vec2f Vec2f.towards(self, Vec2f target, float max_distance) => towards(self, target, max_distance); +fn Vec3f Vec3f.towards(self, Vec3f target, float max_distance) => towards(self, target, max_distance); +fn Vec4f Vec4f.towards(self, Vec4f target, float max_distance) => towards(self, target, max_distance); +fn Vec2 Vec2.towards(self, Vec2 target, double max_distance) => towards(self, target, max_distance); +fn Vec3 Vec3.towards(self, Vec3 target, double max_distance) => towards(self, target, max_distance); +fn Vec4 Vec4.towards(self, Vec4 target, double max_distance) => towards(self, target, max_distance); -fn Vec3f Vec3f.cross(Vec3f v1, Vec3f v2) => cross3(v1, v2); -fn Vec3 Vec3.cross(Vec3 v1, Vec3 v2) => cross3(v1, v2); +fn Vec3f Vec3f.cross(self, Vec3f v2) => cross3(self, v2); +fn Vec3 Vec3.cross(self, Vec3 v2) => cross3(self, v2); -fn Vec3f Vec3f.perpendicular(Vec3f v) => perpendicular3(v); -fn Vec3 Vec3.perpendicular(Vec3 v) => perpendicular3(v); +fn Vec3f Vec3f.perpendicular(self) => perpendicular3(self); +fn Vec3 Vec3.perpendicular(self) => perpendicular3(self); -fn Vec3f Vec3f.barycenter(Vec3f p, Vec3f a, Vec3f b, Vec3f c) => barycenter3(p, a, b, c); -fn Vec3 Vec3.barycenter(Vec3 p, Vec3 a, Vec3 b, Vec3 c) => barycenter3(p, a, b, c); +fn Vec3f Vec3f.barycenter(self, Vec3f a, Vec3f b, Vec3f c) => barycenter3(self, a, b, c); +fn Vec3 Vec3.barycenter(self, Vec3 a, Vec3 b, Vec3 c) => barycenter3(self, a, b, c); -fn Vec3f Vec3f.transform(Vec3f v, Matrix4f mat) => transform3(v, mat); -fn Vec3 Vec3.transform(Vec3 v, Matrix4 mat) => transform3(v, mat); +fn Vec3f Vec3f.transform(self, Matrix4f mat) => transform3(self, mat); +fn Vec3 Vec3.transform(self, Matrix4 mat) => transform3(self, mat); -fn float Vec3f.angle(Vec3f v1, Vec3f v2) => angle3(v1, v2); -fn double Vec3.angle(Vec3 v1, Vec3 v2) => angle3(v1, v2); +fn float Vec3f.angle(self, Vec3f v2) => angle3(self, v2); +fn double Vec3.angle(self, Vec3 v2) => angle3(self, v2); -fn Vec3f Vec3f.refract(Vec3f v, Vec3f n, float r) => refract3(v, n, r); -fn Vec3 Vec3.refract(Vec3 v, Vec3 n, double r) => refract3(v, n, r); +fn Vec3f Vec3f.refract(self, Vec3f n, float r) => refract3(self, n, r); +fn Vec3 Vec3.refract(self, Vec3 n, double r) => refract3(self, n, r); fn void ortho_normalize(Vec3f* v1, Vec3f* v2) => ortho_normalize3(v1, v2); fn void ortho_normalized(Vec3* v1, Vec3* v2) => ortho_normalize3(v1, v2); @@ -69,14 +69,14 @@ fn void ortho_normalized(Vec3* v1, Vec3* v2) => ortho_normalize3(v1, v2); fn Matrix4f matrix4f_look_at(Vec3f eye, Vec3f target, Vec3f up) => matrix_look_at(Matrix4f, eye, target, up); fn Matrix4 matrix4_look_at(Vec3 eye, Vec3 target, Vec3 up) => matrix_look_at(Matrix4, eye, target, up); -fn Vec3f Vec3f.rotate_quat(Vec3f v, Quaternionf q) => rotate_by_quat3(v, q); -fn Vec3 Vec3.rotate_quat(Vec3 v, Quaternion q) => rotate_by_quat3(v, q); +fn Vec3f Vec3f.rotate_quat(self, Quaternionf q) => rotate_by_quat3(self, q); +fn Vec3 Vec3.rotate_quat(self, Quaternion q) => rotate_by_quat3(self, q); -fn Vec3f Vec3f.rotate_axis(Vec3f v, Vec3f axis, float angle) => rotate_axis_angle(v, axis, angle); -fn Vec3 Vec3.rotate_axis(Vec3 v, Vec3 axis, double angle) => rotate_axis_angle(v, axis, angle); +fn Vec3f Vec3f.rotate_axis(self, Vec3f axis, float angle) => rotate_axis_angle(self, axis, angle); +fn Vec3 Vec3.rotate_axis(self, Vec3 axis, double angle) => rotate_axis_angle(self, axis, angle); -fn Vec3f Vec3f.unproject(Vec3f v, Matrix4f projection, Matrix4f view) => unproject3(v, projection, view); -fn Vec3 Vec3.unproject(Vec3 v, Matrix4 projection, Matrix4 view) => unproject3(v, projection, view); +fn Vec3f Vec3f.unproject(self, Matrix4f projection, Matrix4f view) => unproject3(self, projection, view); +fn Vec3 Vec3.unproject(self, Matrix4 projection, Matrix4 view) => unproject3(self, projection, view); macro towards(v, target, max_distance) @private { diff --git a/lib/std/time/clock.c3 b/lib/std/time/clock.c3 index 643ffdbe1..91436eeba 100644 --- a/lib/std/time/clock.c3 +++ b/lib/std/time/clock.c3 @@ -9,15 +9,15 @@ fn Clock now() $endif } -fn NanoDuration Clock.mark(Clock* this) +fn NanoDuration Clock.mark(&self) { Clock mark = now(); - NanoDuration diff = (NanoDuration)(mark - *this); - *this = mark; + NanoDuration diff = (NanoDuration)(mark - *self); + *self = mark; return diff; } -fn NanoDuration Clock.to_now(Clock this) +fn NanoDuration Clock.to_now(self) { - return (NanoDuration)(now() - this); + return (NanoDuration)(now() - self); } \ No newline at end of file diff --git a/lib/std/time/datetime.c3 b/lib/std/time/datetime.c3 index 4619078dd..1636b9a61 100644 --- a/lib/std/time/datetime.c3 +++ b/lib/std/time/datetime.c3 @@ -20,13 +20,13 @@ fn DateTime from_date(int year, Month month = JANUARY, int day = 1, int hour = 0 return dt; } -fn TzDateTime DateTime.to_local(DateTime* this) +fn TzDateTime DateTime.to_local(&self) { Tm tm @noinit; - Time_t time_t = (Time_t)this.time.to_seconds(); + Time_t time_t = (Time_t)self.time.to_seconds(); libc::localtime_r(&time_t, &tm); TzDateTime dt; - dt.usec = (int)((long)this.time % (long)time::MICROSECONDS_PER_SECOND); + dt.usec = (int)((long)self.time % (long)time::MICROSECONDS_PER_SECOND); dt.sec = (char)tm.tm_sec; dt.min = (char)tm.tm_min; dt.hour = (char)tm.tm_hour; @@ -35,7 +35,7 @@ fn TzDateTime DateTime.to_local(DateTime* this) dt.year = tm.tm_year + 1900; dt.weekday = !tm.tm_wday ? Weekday.SUNDAY : (Weekday)tm.tm_wday + 1; dt.year_day = (ushort)tm.tm_yday; - dt.time = this.time; + dt.time = self.time; $if $defined(tm.tm_gmtoff): dt.gmt_offset = (int)tm.tm_gmtoff; $else @@ -54,7 +54,7 @@ fn TzDateTime DateTime.to_local(DateTime* this) * @require sec >= 0 && sec < 60 * @require us >= 0 && us < 999_999 **/ -fn void DateTime.set_date(DateTime *this, int year, Month month = JANUARY, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0) +fn void DateTime.set_date(&self, int year, Month month = JANUARY, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0) { Tm tm; tm.tm_sec = sec; @@ -64,43 +64,43 @@ fn void DateTime.set_date(DateTime *this, int year, Month month = JANUARY, int d tm.tm_mday = day; tm.tm_year = year - 1900; Time_t time = libc::timegm(&tm); - this.set_time((Time)(time * (long)time::MICROSECONDS_PER_SECOND + us)); + self.set_time((Time)(time * (long)time::MICROSECONDS_PER_SECOND + us)); } -fn void DateTime.set_time(DateTime* this, Time time) +fn void DateTime.set_time(&self, Time time) { Tm tm @noinit; Time_t time_t = (Time_t)time.to_seconds(); libc::gmtime_r(&time_t, &tm); - this.usec = (int)((long)time % (long)time::MICROSECONDS_PER_SECOND); - this.sec = (char)tm.tm_sec; - this.min = (char)tm.tm_min; - this.hour = (char)tm.tm_hour; - this.day = (char)tm.tm_mday; - this.month = (Month)tm.tm_mon; - this.year = tm.tm_year + 1900; - this.weekday = !tm.tm_wday ? Weekday.SUNDAY : (Weekday)tm.tm_wday + 1; - this.year_day = (ushort)tm.tm_yday; - this.time = time; + self.usec = (int)((long)time % (long)time::MICROSECONDS_PER_SECOND); + self.sec = (char)tm.tm_sec; + self.min = (char)tm.tm_min; + self.hour = (char)tm.tm_hour; + self.day = (char)tm.tm_mday; + self.month = (Month)tm.tm_mon; + self.year = tm.tm_year + 1900; + self.weekday = !tm.tm_wday ? Weekday.SUNDAY : (Weekday)tm.tm_wday + 1; + self.year_day = (ushort)tm.tm_yday; + self.time = time; } -fn DateTime DateTime.add_seconds(DateTime* date, int seconds) => from_time(date.time.add_seconds(seconds)); -fn DateTime DateTime.add_minutes(DateTime* date, int minutes) => from_time(date.time.add_minutes(minutes)); -fn DateTime DateTime.add_hours(DateTime* date, int hours) => from_time(date.time.add_hours(hours)); -fn DateTime DateTime.add_days(DateTime* date, int days) => from_time(date.time.add_days(days)); -fn DateTime DateTime.add_weeks(DateTime* date, int weeks) => from_time(date.time.add_weeks(weeks)); +fn DateTime DateTime.add_seconds(&self, int seconds) => from_time(self.time.add_seconds(seconds)); +fn DateTime DateTime.add_minutes(&self, int minutes) => from_time(self.time.add_minutes(minutes)); +fn DateTime DateTime.add_hours(&self, int hours) => from_time(self.time.add_hours(hours)); +fn DateTime DateTime.add_days(&self, int days) => from_time(self.time.add_days(days)); +fn DateTime DateTime.add_weeks(&self, int weeks) => from_time(self.time.add_weeks(weeks)); -fn DateTime DateTime.add_years(DateTime* date, int years) +fn DateTime DateTime.add_years(&self, int years) { - if (!years) return *date; - return from_date(date.year + years, date.month, date.day, date.hour, date.min, date.sec, date.usec); + if (!years) return *self; + return from_date(self.year + years, self.month, self.day, self.hour, self.min, self.sec, self.usec); } -fn DateTime DateTime.add_months(DateTime* date, int months) +fn DateTime DateTime.add_months(&self, int months) { - if (months == 0) return *date; - int year = date.year; - int month = date.month.ordinal; + if (months == 0) return *self; + int year = self.year; + int month = self.month.ordinal; switch { case months % 12 == 0: @@ -118,7 +118,7 @@ fn DateTime DateTime.add_months(DateTime* date, int months) year += month / 12; month %= 12; } - return from_date(year, (Month)month, date.day, date.hour, date.min, date.sec, date.usec); + return from_date(year, (Month)month, self.day, self.hour, self.min, self.sec, self.usec); } fn DateTime from_time(Time time) @@ -128,48 +128,48 @@ fn DateTime from_time(Time time) return dt; } -fn Time DateTime.to_time(DateTime* this) @inline +fn Time DateTime.to_time(&self) @inline { - return this.time; + return self.time; } -fn bool DateTime.after(DateTime* this, DateTime compare) +fn bool DateTime.after(&self, DateTime compare) { - return this.time > compare.time; + return self.time > compare.time; } -fn bool DateTime.before(DateTime* this, DateTime compare) +fn bool DateTime.before(&self, DateTime compare) { - return this.time < compare.time; + return self.time < compare.time; } -fn int DateTime.compare_to(DateTime* this, DateTime compare) +fn int DateTime.compare_to(&self, DateTime compare) { switch { - case this.time > compare.time: return 1; - case this.time < compare.time: return -1; + case self.time > compare.time: return 1; + case self.time < compare.time: return -1; default: return 0; } } -fn int DateTime.diff_years(DateTime *to, DateTime from) +fn int DateTime.diff_years(&self, DateTime from) { - int year_diff = to.year - from.year; + int year_diff = self.year - from.year; switch { - case year_diff < 0: return -from.diff_years(*to); + case year_diff < 0: return -from.diff_years(*self); case year_diff == 0: return 0; } - if (to.year_day < from.year_day) year_diff--; + if (self.year_day < from.year_day) year_diff--; return year_diff; } -fn double DateTime.diff_sec(DateTime to, DateTime from) +fn double DateTime.diff_sec(self, DateTime from) { - return (double)to.time.diff_us(from.time) / (double)time::MICROSECONDS_PER_SECOND; + return (double)self.time.diff_us(from.time) / (double)time::MICROSECONDS_PER_SECOND; } -fn TimeDuration DateTime.diff_us(DateTime to, DateTime from) +fn TimeDuration DateTime.diff_us(self, DateTime from) { - return to.time.diff_us(from.time); + return self.time.diff_us(from.time); } \ No newline at end of file diff --git a/resources/examples/contextfree/guess_number.c3 b/resources/examples/contextfree/guess_number.c3 index a1086e1af..63041b6fb 100644 --- a/resources/examples/contextfree/guess_number.c3 +++ b/resources/examples/contextfree/guess_number.c3 @@ -52,7 +52,6 @@ fn int! askGuessMulti(int high) } return result; } - unreachable(); } fn void! Game.play(Game *game) diff --git a/resources/examples/fannkuch-redux.c3 b/resources/examples/fannkuch-redux.c3 index cfd8b7400..4155d40bd 100644 --- a/resources/examples/fannkuch-redux.c3 +++ b/resources/examples/fannkuch-redux.c3 @@ -64,7 +64,6 @@ fn int fannkuchredux(int n) } perm_count++; } - return 0; } fn int main(int argc, char** argv) diff --git a/resources/examples/fannkuch-redux2.c3 b/resources/examples/fannkuch-redux2.c3 index dcd7646c8..8793b3366 100644 --- a/resources/examples/fannkuch-redux2.c3 +++ b/resources/examples/fannkuch-redux2.c3 @@ -61,7 +61,6 @@ fn int fannkuchredux(int n) } perm_count++; } - return 0; } fn void! main(String[] argv) diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 86edcd3b0..987156ed0 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -144,7 +144,7 @@ void **tilde_gen(Module** modules, unsigned module_count) #endif -static const char *build_base_name(void) +const char *build_base_name(void) { const char *name; if (active_target.name) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index c553eeb3e..ff04d18f3 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1001,6 +1001,7 @@ typedef struct typedef struct { AstId first_stmt; + bool is_noreturn; Decl **params; BlockExit **block_exit; } ExprMacroBlock; @@ -2069,6 +2070,7 @@ void **llvm_gen(Module** modules, unsigned module_count); void **tilde_gen(Module** modules, unsigned module_count); void header_gen(Module **modules, unsigned module_count); +const char *build_base_name(void); void global_context_clear_errors(void); void global_context_add_type(Type *type); diff --git a/src/compiler/headers.c b/src/compiler/headers.c index ccb997cbe..7baf0a1c7 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -540,8 +540,9 @@ void header_gen(Module **modules, unsigned module_count) { HTable table; htable_init(&table, 1024); - const char *filename = str_printf("foo_fn.h"); - const char *filename_types = str_printf("foo_types.h"); + const char *name = build_base_name(); + const char *filename = str_printf("%s_fn.h", name); + const char *filename_types = str_printf("%s_types.h", name); FILE *file = fopen(filename, "w"); FILE *file_types = fopen(filename_types, "w"); OUT(file_types, "#include \n"); @@ -553,7 +554,7 @@ void header_gen(Module **modules, unsigned module_count) OUT(file_types, "typedef struct { void* ptr; size_t len; } c3slice_t;\n"); OUT(file_types, "typedef struct { void* ptr; c3typeid_t type; } c3any_t;\n"); OUT(file_types, "\n#endif\n\n"); - OUTPUT("#include \"foo_types.h\"\n"); + OUTPUT("#include \"%s_types.h\"\n", name); for (unsigned i = 0; i < module_count; i++) { @@ -595,7 +596,6 @@ void header_gen(Module **modules, unsigned module_count) } OUTPUT("\n/* Functions */\n"); - for (unsigned i = 0; i < module_count; i++) { Module *module = modules[i]; diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 92272ae1c..3199e49d8 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -5917,6 +5917,10 @@ static inline void llvm_emit_macro_block(GenContext *context, BEValue *be_value, llvm_debug_push_lexical_scope(context, astptr(expr->macro_block.first_stmt)->span); } llvm_emit_return_block(context, be_value, expr->type, expr->macro_block.first_stmt, expr->macro_block.block_exit); + if (expr->macro_block.is_noreturn && context->current_block && context->current_block_is_target) + { + llvm_emit_unreachable(context); + } if (llvm_use_debug(context)) { llvm_debug_scope_pop(context); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 011111219..4bd572753 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -744,7 +744,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, if (type_parent && params && params[0] && !params[0]->var.type_info) { TypeInfo *method_parent = type_infoptr(type_parent); - if (!sema_resolve_type_info(context, method_parent)) return false; + if (!sema_resolve_type_info_maybe_inferred(context, method_parent, true)) return false; Decl *param = params[0]; Type *inferred_type = NULL; switch (param->var.kind) diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 67a986ccc..2b401a82d 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1944,9 +1944,9 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s params = macro_context.macro_params; bool is_no_return = decl->func_decl.signature.attrs.noreturn; - if (!vec_size(macro_context.returns) || !macro_context.active_scope.jump_end) + if (!vec_size(macro_context.returns)) { - if (rtype && rtype != type_void) + if (rtype && rtype != type_void && !macro_context.active_scope.jump_end) { SEMA_ERROR(decl, "Missing return in macro that should evaluate to %s.", @@ -2053,6 +2053,7 @@ NOT_CT: call_expr->macro_block.first_stmt = body->compound_stmt.first_stmt; call_expr->macro_block.params = params; call_expr->macro_block.block_exit = block_exit_ref; + call_expr->macro_block.is_noreturn = is_no_return; EXIT: assert(context->active_scope.defer_last == context->active_scope.defer_start); context->active_scope = old_scope; diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index a2f89a378..c85fbf5bd 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -345,6 +345,7 @@ static inline bool analyse_func_body(SemaContext *context, Decl *decl) } // Don't analyse functions that are tests. if (decl->func_decl.attr_test && !active_target.testing) return true; + if (!sema_analyse_function_body(context, decl)) return decl_poison(decl); return true; } diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 65e488919..6c6124c3a 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1045,11 +1045,20 @@ static inline bool sema_analyse_expr_stmt(SemaContext *context, Ast *statement) expr->call_expr.result_unused = true; } if (!sema_analyse_expr(context, expr)) return false; - if (expr->expr_kind == EXPR_CALL && expr->call_expr.no_return) context->active_scope.jump_end = true; - // Remove all const statements. - if (expr_is_const(expr)) + switch (expr->expr_kind) { - statement->ast_kind = AST_NOP_STMT; + case EXPR_CALL: + if (expr->call_expr.no_return) context->active_scope.jump_end = true; + break; + case EXPR_MACRO_BLOCK: + if (expr->macro_block.is_noreturn) context->active_scope.jump_end = true; + break; + case EXPR_CONST: + // Remove all const statements. + statement->ast_kind = AST_NOP_STMT; + break; + default: + break; } return true; } @@ -1213,7 +1222,7 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement) SCOPE_OUTER_END; - if (statement->for_stmt.flow.no_exit || (is_infinite && !statement->for_stmt.flow.has_break)) + if (is_infinite && !statement->for_stmt.flow.has_break) { context->active_scope.jump_end = true; } @@ -2201,12 +2210,12 @@ static bool sema_analyse_switch_body(SemaContext *context, Ast *statement, Sourc success = success && (!body || sema_analyse_compound_statement_no_scope(context, body)); POP_BREAK(); POP_NEXT(); - all_jump_end &= (!body | context->active_scope.jump_end); + if (!body && i < case_count - 1) continue; + all_jump_end &= context->active_scope.jump_end; SCOPE_END; } statement->flow.no_exit = all_jump_end; statement->switch_stmt.flow.if_chain = if_chain || max_ranged; - if (!success) return false; return success; } @@ -2695,21 +2704,6 @@ FAILED: static inline bool sema_analyse_statement_inner(SemaContext *context, Ast *statement) { - if (statement->ast_kind == AST_POISONED) - { - return false; - } - if (context->active_scope.jump_end && !context->active_scope.allow_dead_code) - { - if (statement->ast_kind == AST_ASSERT_STMT) - { - context->active_scope.allow_dead_code = true; - return true; - } - //ERROR_NODE(statement, "This code will never execute."); - context->active_scope.allow_dead_code = true; - //return false; - } switch (statement->ast_kind) { case AST_POISONED: @@ -2780,8 +2774,25 @@ static inline bool sema_analyse_statement_inner(SemaContext *context, Ast *state bool sema_analyse_statement(SemaContext *context, Ast *statement) { - if (sema_analyse_statement_inner(context, statement)) return true; - return ast_poison(statement); + if (statement->ast_kind == AST_POISONED) return false; + bool dead_code = context->active_scope.jump_end; + if (!sema_analyse_statement_inner(context, statement)) return ast_poison(statement); + if (dead_code) + { + if (!context->active_scope.allow_dead_code) + { + context->active_scope.allow_dead_code = true; + // If we start with an don't start with an assert AND the scope is a macro, then it's bad. + if (statement->ast_kind != AST_ASSERT_STMT && statement->ast_kind != AST_NOP_STMT && !(context->active_scope.flags & SCOPE_MACRO)) + { + SEMA_ERROR(statement, "This code will never execute."); + return ast_poison(statement); + } + // Remove it + statement->ast_kind = AST_NOP_STMT; + } + } + return true; } @@ -3033,26 +3044,9 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func) { sema_append_contract_asserts(assert_first, body); Type *canonical_rtype = type_no_optional(prototype->rtype)->canonical; - // Insert an implicit return - if (canonical_rtype == type_void) - { - AstId *next_id = &body->compound_stmt.first_stmt; - SourceSpan span = body->span; - if (*next_id) - { - Ast *last = ast_last(astptr(*next_id)); - // Cleanup later - if (last->ast_kind == AST_RETURN_STMT) goto SKIP_NEW_RETURN; - span = last->span; - next_id = &last->next; - } - Ast *ret = new_ast(AST_RETURN_STMT, span); - ast_append(&next_id, ret); - SKIP_NEW_RETURN:; - } if (!sema_analyse_compound_statement_no_scope(context, body)) return false; assert(context->active_scope.depth == 1); - if (!context->active_scope.jump_end) + if (!context->active_scope.jump_end && canonical_rtype != type_void) { SEMA_ERROR(func, "Missing return statement at the end of the function."); return false; diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 84d99e64f..9922d2ebb 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -35,8 +35,6 @@ bool sema_resolve_type_info_maybe_inferred(SemaContext *context, TypeInfo *type_ return sema_resolve_type(context, type_info, allow_inferred_type, false); } - - bool sema_resolve_array_like_len(SemaContext *context, TypeInfo *type_info, ArraySize *len_ref) { // Get the expression describing the length. diff --git a/test/test_suite/abi/darwinx64_1.c3t b/test/test_suite/abi/darwinx64_1.c3t index bbdf16a09..22f815b5b 100644 --- a/test/test_suite/abi/darwinx64_1.c3t +++ b/test/test_suite/abi/darwinx64_1.c3t @@ -32,7 +32,7 @@ struct Struct8 int b; } -fn Struct8 f8_1() { while (1) {} return Struct8 {}; } +fn Struct8 f8_1() { while (0) {} return Struct8 {}; } fn void f8_2(Struct8 a0) {} /* #expect: test.ll diff --git a/test/test_suite/abi/darwinx64_2.c3t b/test/test_suite/abi/darwinx64_2.c3t index fa5e3bd13..3677e1034 100644 --- a/test/test_suite/abi/darwinx64_2.c3t +++ b/test/test_suite/abi/darwinx64_2.c3t @@ -6,13 +6,13 @@ struct St12 { int a @align(16); } -fn St12 f12_0() { while (1) {}; unreachable(); } +fn St12 f12_0() { while (1) {} } fn void f12_1(St12 a0) {} struct St13_0 { long[3] f0; } struct St13_1 { long[2] f0; } fn St13_0 f13(int a, int b, int c, int d, - St13_1 e, int f) { while (1) {}; unreachable(); } + St13_1 e, int f) { while (1) {} } fn void f14(int a, int b, int c, int d, int e, int f, ichar x) {} diff --git a/test/test_suite/assert/assertf.c3t b/test/test_suite/assert/assertf.c3t index 194229887..ae1b91263 100644 --- a/test/test_suite/assert/assertf.c3t +++ b/test/test_suite/assert/assertf.c3t @@ -18,7 +18,6 @@ entry: %taddr = alloca i64, align 8 %varargslots = alloca [2 x %any], align 16 %indirectarg = alloca %"any[]", align 8 - %reterr = alloca i64, align 8 store i64 0, ptr %i, align 8 br label %loop.cond diff --git a/test/test_suite/assert/unreachable.c3t b/test/test_suite/assert/unreachable.c3t index 1d3d66b60..43dff795f 100644 --- a/test/test_suite/assert/unreachable.c3t +++ b/test/test_suite/assert/unreachable.c3t @@ -9,7 +9,6 @@ fn void test() int x = foo(); if (x > 0) return; unreachable(); - x++; } @@ -36,10 +35,4 @@ if.exit: ; preds = %entry store %"any[]" zeroinitializer, ptr %indirectarg, align 8 call void @std.core.builtin.panicf(ptr %lo, i64 %hi, ptr @.str.1, i64 14, ptr @.str.2, i64 4, i32 10, ptr byval(%"any[]") align 8 %indirectarg) unreachable -after.unreachable: ; No predecessors! - %4 = load i32, ptr %x, align 4 - %add = add i32 %4, 1 - store i32 %add, ptr %x, align 4 - ret void -} - +} \ No newline at end of file diff --git a/test/test_suite/clang/2002-01_02.c3t b/test/test_suite/clang/2002-01_02.c3t index 7b136a9a3..2810b1ac0 100644 --- a/test/test_suite/clang/2002-01_02.c3t +++ b/test/test_suite/clang/2002-01_02.c3t @@ -73,7 +73,6 @@ fn int do_merge(QuadEdge ldo, QuadEdge rdo) { return (int)((iptr)(basel.next)); } } - return 1; } fn int test(int x) { @@ -223,8 +222,6 @@ if.then: ; preds = %loop.body ret i32 %ptrxi if.exit: ; preds = %loop.body br label %loop.body -loop.exit: ; No predecessors! - ret i32 1 } define i32 @test.test(i32 %0) #0 { diff --git a/test/test_suite/errors/optional_inits.c3t b/test/test_suite/errors/optional_inits.c3t index 680366232..c7c999b0e 100644 --- a/test/test_suite/errors/optional_inits.c3t +++ b/test/test_suite/errors/optional_inits.c3t @@ -39,7 +39,6 @@ entry: %x.f = alloca i64, align 8 %y = alloca %Bar, align 4 %error_var = alloca i64, align 8 - %reterr = alloca i64, align 8 store i64 ptrtoint (ptr @"test.Foo$MY_VAL1" to i64), ptr %x.f, align 8 %optval = load i64, ptr %x.f, align 8 %not_err = icmp eq i64 %optval, 0 @@ -69,7 +68,6 @@ entry: %x.f = alloca i64, align 8 %y = alloca %Bar, align 4 %error_var = alloca i64, align 8 - %reterr = alloca i64, align 8 store i32 0, ptr %x, align 4 store i64 0, ptr %x.f, align 8 %optval = load i64, ptr %x.f, align 8 diff --git a/test/test_suite/errors/or_and_rethrow.c3t b/test/test_suite/errors/or_and_rethrow.c3t index 22c7afeea..288a32e9d 100644 --- a/test/test_suite/errors/or_and_rethrow.c3t +++ b/test/test_suite/errors/or_and_rethrow.c3t @@ -60,7 +60,6 @@ entry: %x18 = alloca %"char[]", align 8 %retparam19 = alloca i64, align 8 %result20 = alloca %File, align 8 - %reterr = alloca i64, align 8 store i32 %0, ptr %taddr, align 4 %1 = insertvalue %any undef, ptr %taddr, 0 %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.int" to i64), 1 @@ -147,7 +146,6 @@ entry: %x7 = alloca %"char[]", align 8 %retparam8 = alloca i64, align 8 %result9 = alloca %File, align 8 - %reterr = alloca i64, align 8 store i32 %0, ptr %taddr, align 4 %1 = insertvalue %any undef, ptr %taddr, 0 %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.int" to i64), 1 diff --git a/test/test_suite/errors/rethrow.c3t b/test/test_suite/errors/rethrow.c3t index f6ea6d328..c94875567 100644 --- a/test/test_suite/errors/rethrow.c3t +++ b/test/test_suite/errors/rethrow.c3t @@ -11,7 +11,6 @@ fn void! test() %i = alloca i32, align 4 %i.f = alloca i64, align 8 %error_var = alloca i64, align 8 - %reterr = alloca i64, align 8 store i64 0, ptr %i.f, align 8 store i32 0, ptr %i, align 4 %optval = load i64, ptr %i.f, align 8 diff --git a/test/test_suite/errors/rethrow_mingw.c3t b/test/test_suite/errors/rethrow_mingw.c3t index 34297c187..9713916ee 100644 --- a/test/test_suite/errors/rethrow_mingw.c3t +++ b/test/test_suite/errors/rethrow_mingw.c3t @@ -15,7 +15,6 @@ entry: %i = alloca i32, align 4 %i.f = alloca i64, align 8 %error_var = alloca i64, align 8 - %reterr = alloca i64, align 8 store i64 0, ptr %i.f, align 8 store i32 0, ptr %i, align 4 %optval = load i64, ptr %i.f, align 8 diff --git a/test/test_suite/expression_block/expression_block_break.c3 b/test/test_suite/expression_block/expression_block_break.c3 index 6202496a0..6b8ae0550 100644 --- a/test/test_suite/expression_block/expression_block_break.c3 +++ b/test/test_suite/expression_block/expression_block_break.c3 @@ -8,6 +8,4 @@ fn int main() { return {| break; return 0; |}; // #error: There is no valid target for 'break', did you make a mistake } - io::printn("I didn't return."); - return 0; } \ No newline at end of file diff --git a/test/test_suite/from_docs/examples_forswitch.c3t b/test/test_suite/from_docs/examples_forswitch.c3t index 8f2c60731..67c01a0e7 100644 --- a/test/test_suite/from_docs/examples_forswitch.c3t +++ b/test/test_suite/from_docs/examples_forswitch.c3t @@ -112,9 +112,6 @@ loop.exit: ; preds = %loop.cond %4 = load ptr, ptr @std.core.builtin.panic, align 8 call void %4(ptr @.panic_msg, i64 19, ptr @.file, i64 21, ptr @.func, i64 11, i32 14) unreachable - -unreachable_block: ; No predecessors! - ret void } ; Function Attrs: nounwind diff --git a/test/test_suite/from_docs/examples_if_catch.c3t b/test/test_suite/from_docs/examples_if_catch.c3t index d3559fee5..6ddf4ddc4 100644 --- a/test/test_suite/from_docs/examples_if_catch.c3t +++ b/test/test_suite/from_docs/examples_if_catch.c3t @@ -46,13 +46,16 @@ fn void main() /* #expect: demo.ll + define i64 @demo.divide(ptr %0, i32 %1, i32 %2) #0 { entry: %reterr = alloca i64, align 8 %eq = icmp eq i32 %2, 0 br i1 %eq, label %if.then, label %if.exit + if.then: ; preds = %entry ret i64 ptrtoint (ptr @"demo.MathError$DIVISION_BY_ZERO" to i64) + if.exit: ; preds = %entry %sifp = sitofp i32 %1 to double %sifp1 = sitofp i32 %2 to double @@ -65,21 +68,24 @@ define i64 @demo.testMayError() #0 { entry: %error_var = alloca i64, align 8 %retparam = alloca double, align 8 - %reterr = alloca i64, align 8 %0 = call i32 @demo.foo() %1 = call i32 @demo.bar() %2 = call i64 @demo.divide(ptr %retparam, i32 %0, i32 %1) %not_err = icmp eq i64 %2, 0 %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %3, label %after_check, label %assign_optional + assign_optional: ; preds = %entry store i64 %2, ptr %error_var, align 8 br label %guard_block + after_check: ; preds = %entry br label %noerr_block + guard_block: ; preds = %assign_optional %4 = load i64, ptr %error_var, align 8 ret i64 %4 + noerr_block: ; preds = %after_check ret i64 0 } @@ -97,46 +103,59 @@ entry: %not_err = icmp eq i64 %2, 0 %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %3, label %after_check, label %assign_optional + assign_optional: ; preds = %entry store i64 %2, ptr %ratio.f, align 8 br label %after_assign + after_check: ; preds = %entry %4 = load double, ptr %retparam, align 8 store double %4, ptr %ratio, align 8 store i64 0, ptr %ratio.f, align 8 br label %after_assign + after_assign: ; preds = %after_check, %assign_optional br label %testblock + testblock: ; preds = %after_assign %optval = load i64, ptr %ratio.f, align 8 %not_err1 = icmp eq i64 %optval, 0 %5 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true) br i1 %5, label %after_check3, label %assign_optional2 + assign_optional2: ; preds = %testblock store i64 %optval, ptr %err, align 8 br label %end_block + after_check3: ; preds = %testblock store i64 0, ptr %err, align 8 br label %end_block + end_block: ; preds = %after_check3, %assign_optional2 %6 = load i64, ptr %err, align 8 %neq = icmp ne i64 %6, 0 br i1 %neq, label %if.then, label %if.exit + if.then: ; preds = %end_block store i64 %6, ptr %switch, align 8 br label %switch.entry + switch.entry: ; preds = %if.then %7 = load i64, ptr %switch, align 8 %eq = icmp eq i64 ptrtoint (ptr @"demo.MathError$DIVISION_BY_ZERO" to i64), %7 br i1 %eq, label %switch.case, label %next_if + switch.case: ; preds = %switch.entry %8 = call i32 (ptr, ...) @printf(ptr @.str) ret void + next_if: ; preds = %switch.entry br label %switch.default + switch.default: ; preds = %next_if %9 = call i32 (ptr, ...) @printf(ptr @.str.1) ret void + if.exit: ; preds = %end_block %10 = load double, ptr %ratio, align 8 %11 = call i32 (ptr, ...) @printf(ptr @.str.2, double %10) diff --git a/test/test_suite/functions/double_return.c3 b/test/test_suite/functions/double_return.c3 new file mode 100644 index 000000000..35dfc0786 --- /dev/null +++ b/test/test_suite/functions/double_return.c3 @@ -0,0 +1,8 @@ +module double_return; + +fn int test(bool pos, bool color) +{ + return 0; + return (int)(pos && color); // #error: never execute +} + diff --git a/test/test_suite/functions/double_return.c3t b/test/test_suite/functions/double_return.c3t deleted file mode 100644 index 7f4875d93..000000000 --- a/test/test_suite/functions/double_return.c3t +++ /dev/null @@ -1,13 +0,0 @@ -module double_return; - -fn int test(bool pos, bool color) -{ - return 0; - return (int)(pos && color); -} - -/* #expect: double_return.ll - -entry: - ret i32 0 -} diff --git a/test/test_suite/macros/macro_body_defer.c3t b/test/test_suite/macros/macro_body_defer.c3t index 714846bad..7f8030983 100644 --- a/test/test_suite/macros/macro_body_defer.c3t +++ b/test/test_suite/macros/macro_body_defer.c3t @@ -44,7 +44,6 @@ fn void! main() return; }; } - printf("Should not reach\n"); } /* #expect: foo.ll @@ -62,7 +61,6 @@ entry: %i1 = alloca i32, align 4 %i3 = alloca i32, align 4 %reterr = alloca i64, align 8 - %reterr5 = alloca i64, align 8 call void (ptr, ...) @printf(ptr @.str) call void (ptr, ...) @printf(ptr @.str.1) call void (ptr, ...) @printf(ptr @.str.2) @@ -73,7 +71,6 @@ entry: %1 = load i32, ptr %i, align 4 call void (ptr, ...) @printf(ptr @.str.5, i32 %1) br label %loop.body - loop.body: ; preds = %entry store i32 3, ptr %i1, align 4 call void (ptr, ...) @printf(ptr @.str.6) @@ -82,10 +79,8 @@ loop.body: ; preds = %entry call void (ptr, ...) @printf(ptr @.str.8, i32 %2) call void (ptr, ...) @printf(ptr @.str.9) br label %loop.exit - loop.exit: ; preds = %loop.body br label %loop.body2 - loop.body2: ; preds = %loop.exit call void (ptr, ...) @printf(ptr @.str.10) store i32 3, ptr %i3, align 4 @@ -95,12 +90,7 @@ loop.body2: ; preds = %loop.exit call void (ptr, ...) @printf(ptr @.str.13, i32 %3) call void (ptr, ...) @printf(ptr @.str.14) ret i64 0 - -loop.exit4: ; No predecessors! - call void (ptr, ...) @printf(ptr @.str.15) - ret i64 0 } - ; Function Attrs: nounwind define i32 @main(i32 %0, ptr %1) #0 { entry: @@ -111,34 +101,27 @@ entry: store i32 %0, ptr %.anon, align 4 store ptr %1, ptr %.anon1, align 8 br label %testblock - testblock: ; preds = %entry %2 = call i64 @foo.main() %not_err = icmp eq i64 %2, 0 %3 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %3, label %after_check, label %assign_optional - assign_optional: ; preds = %testblock store i64 %2, ptr %temp_err, align 8 br label %end_block - after_check: ; preds = %testblock store i64 0, ptr %temp_err, align 8 br label %end_block - end_block: ; preds = %after_check, %assign_optional %4 = load i64, ptr %temp_err, align 8 %neq = icmp ne i64 %4, 0 br i1 %neq, label %if.then, label %if.exit - if.then: ; preds = %end_block store i32 1, ptr %blockret, align 4 br label %expr_block.exit - if.exit: ; preds = %end_block store i32 0, ptr %blockret, align 4 br label %expr_block.exit - expr_block.exit: ; preds = %if.exit, %if.then %5 = load i32, ptr %blockret, align 4 ret i32 %5 diff --git a/test/test_suite/statements/defer_break.c3t b/test/test_suite/statements/defer_break.c3t index c20d7f7ac..df8159196 100644 --- a/test/test_suite/statements/defer_break.c3t +++ b/test/test_suite/statements/defer_break.c3t @@ -40,7 +40,6 @@ fn int main(int argc, char** argv) defer defer9(); defer10(); break; - defer11(); } return 0; } diff --git a/test/test_suite/statements/defer_return.c3t b/test/test_suite/statements/defer_return.c3t index 9d9c43d6f..968b278b7 100644 --- a/test/test_suite/statements/defer_return.c3t +++ b/test/test_suite/statements/defer_return.c3t @@ -29,7 +29,6 @@ fn int main(int argc, char **argv) defer test7(); test8(); return 2 + 2; - defer test9(); } return 0 + argc; } diff --git a/test/test_suite/statements/for.c3 b/test/test_suite/statements/for.c3 index 3dc2e9a52..eff1fcdc7 100644 --- a/test/test_suite/statements/for.c3 +++ b/test/test_suite/statements/for.c3 @@ -7,7 +7,6 @@ fn int test1() for (int x = 0;;) { } - return 0; } fn int test2() @@ -15,7 +14,6 @@ fn int test2() for (int x = 0; 1 ;) { } - return 0; } fn int test3() @@ -23,5 +21,4 @@ fn int test3() for (; 1 ;2) { } - return 0; } diff --git a/test/test_suite/statements/for_empty.c3 b/test/test_suite/statements/for_empty.c3 index 3536032da..d795a0173 100644 --- a/test/test_suite/statements/for_empty.c3 +++ b/test/test_suite/statements/for_empty.c3 @@ -1,7 +1,8 @@ -fn int main() +fn int test1() { for (;;); - +} +fn int test2() +{ for (;;) {} - return 0; -} \ No newline at end of file +} diff --git a/test/test_suite/statements/infinite_do_while.c3t b/test/test_suite/statements/infinite_do_while.c3t index 146f729a0..b980fe179 100644 --- a/test/test_suite/statements/infinite_do_while.c3t +++ b/test/test_suite/statements/infinite_do_while.c3t @@ -27,9 +27,6 @@ entry: loop.body: ; preds = %loop.body, %entry call void @test.testx() br label %loop.body - -loop.exit: ; No predecessors! - ret void } define void @test.test2() #0 { @@ -40,6 +37,4 @@ loop.body: ; preds = %loop.body, %entry call void @test.testx() br label %loop.body -loop.exit: ; No predecessors! - ret void -} +} \ No newline at end of file diff --git a/test/test_suite/statements/return_with_other_at_end.c3 b/test/test_suite/statements/return_with_other_at_end.c3 index 09c6384e6..5dc093294 100644 --- a/test/test_suite/statements/return_with_other_at_end.c3 +++ b/test/test_suite/statements/return_with_other_at_end.c3 @@ -2,6 +2,6 @@ fn int testReturnWithOtherAtEnd() { int i = 0; return i; - if (i == 10) i++; + if (i == 10) i++; // #error: This code will i = i + 2; }