From b46c7907560edaa1412392310b232dbc6955fde4 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Thu, 16 Oct 2025 20:21:44 -0400 Subject: [PATCH] WIP(Untested, compiles): Grime progress --- code2/grime/allocator_interface.odin | 22 ++++----- code2/grime/assert.odin | 17 ++++--- code2/grime/dynamic_array.odin | 74 +++++++++++++--------------- code2/grime/pkg_mappings.odin | 2 +- 4 files changed, 57 insertions(+), 58 deletions(-) diff --git a/code2/grime/allocator_interface.odin b/code2/grime/allocator_interface.odin index fdc3c0e..04d3376 100644 --- a/code2/grime/allocator_interface.odin +++ b/code2/grime/allocator_interface.odin @@ -205,7 +205,7 @@ mem_save_point :: proc(ainfo := context.allocator, loc := #caller_location) -> A resolve_allocator_proc(ainfo.procedure)({data = ainfo.data, op = .SavePoint, loc = loc}, & out) return out.save_point } -mem_alloc :: proc(size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, ainfo : $Type = context.allocator, loc := #caller_location) -> ([]byte, AllocatorError) { +mem_alloc :: proc(size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: bool = false, ainfo : $Type = context.allocator, loc := #caller_location) -> ([]byte, AllocatorError) { assert(ainfo.procedure != nil) input := AllocatorProc_In { data = ainfo.data, @@ -218,7 +218,7 @@ mem_alloc :: proc(size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: resolve_allocator_proc(ainfo.procedure)(input, & output) return output.allocation, output.error } -mem_grow :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, ainfo := context.allocator, loc := #caller_location) -> []byte { +mem_grow :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: bool = false, ainfo := context.allocator, loc := #caller_location) -> ([]byte, AllocatorError) { assert(ainfo.procedure != nil) input := AllocatorProc_In { data = ainfo.data, @@ -230,9 +230,9 @@ mem_grow :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAU } output: AllocatorProc_Out resolve_allocator_proc(ainfo.procedure)(input, & output) - return output.allocation + return output.allocation, output.error } -mem_resize :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, ainfo := context.allocator, loc := #caller_location) -> []byte { +mem_resize :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: bool = false, ainfo := context.allocator, loc := #caller_location) -> ([]byte, AllocatorError) { assert(ainfo.procedure != nil) input := AllocatorProc_In { data = ainfo.data, @@ -244,9 +244,9 @@ mem_resize :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEF } output: AllocatorProc_Out resolve_allocator_proc(ainfo.procedure)(input, & output) - return output.allocation + return output.allocation, output.error } -mem_shrink :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, ainfo := context.allocator, loc := #caller_location) -> []byte { +mem_shrink :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: bool = false, ainfo := context.allocator, loc := #caller_location) -> ([]byte, AllocatorError) { assert(ainfo.procedure != nil) input := AllocatorProc_In { data = ainfo.data, @@ -258,10 +258,10 @@ mem_shrink :: proc(mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEF } output: AllocatorProc_Out resolve_allocator_proc(ainfo.procedure)(input, & output) - return output.allocation + return output.allocation, output.error } -alloc_type :: proc($Type: typeid, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, ainfo := context.allocator, loc := #caller_location) -> ^Type { +alloc_type :: proc($Type: typeid, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: bool = false, ainfo := context.allocator, loc := #caller_location) -> (^Type, AllocatorError) { assert(ainfo.procedure != nil) input := AllocatorProc_In { data = ainfo.data, @@ -272,9 +272,9 @@ alloc_type :: proc($Type: typeid, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no } output: AllocatorProc_Out resolve_allocator_proc(ainfo.procedure)(input, & output) - return transmute(^Type) raw_data(output.allocation) + return transmute(^Type) raw_data(output.allocation), output.error } -alloc_slice :: proc($SliceType: typeid / []$Type, num : int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, ainfo := context.allocator, loc := #caller_location) -> []Type { +alloc_slice :: proc($SliceType: typeid / []$Type, num: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: bool = false, ainfo := context.allocator, loc := #caller_location) -> ([]Type, AllocatorError) { assert(ainfo.procedure != nil) input := AllocatorProc_In { data = ainfo.data, @@ -285,5 +285,5 @@ alloc_slice :: proc($SliceType: typeid / []$Type, num : int, alignment: int = ME } output: AllocatorProc_Out resolve_allocator_proc(ainfo.procedure)(input, & output) - return transmute([]Type) slice(raw_data(output.allocation), num) + return transmute([]Type) slice(raw_data(output.allocation), num), output.error } diff --git a/code2/grime/assert.odin b/code2/grime/assert.odin index 34cc98b..c96f61b 100644 --- a/code2/grime/assert.odin +++ b/code2/grime/assert.odin @@ -2,21 +2,24 @@ package grime // Below should be defined per-package -@(disabled = ODIN_DEBUG == false) -ensure :: #force_inline proc( condition : b32, msg : string, location := #caller_location ) { - if condition do return +ensure :: #force_inline proc(condition: bool, msg: string, location := #caller_location) -> bool { + if condition do return true log_print( msg, LoggerLevel.Warning, location ) - debug_trap() + when ODIN_DEBUG == false do return false + else { + debug_trap() + return false + } } // TODO(Ed) : Setup exit codes! -fatal :: #force_inline proc( msg : string, exit_code : int = -1, location := #caller_location ) { +fatal :: #force_inline proc(msg: string, exit_code: int = -1, location := #caller_location) { log_print( msg, LoggerLevel.Fatal, location ) debug_trap() process_exit( exit_code ) } // TODO(Ed) : Setup exit codes! -verify :: #force_inline proc( condition : b32, msg : string, exit_code : int = -1, location := #caller_location ) { - if condition do return +verify :: #force_inline proc(condition: bool, msg: string, exit_code: int = -1, location := #caller_location) -> bool { + if condition do return true log_print( msg, LoggerLevel.Fatal, location ) debug_trap() process_exit( exit_code ) diff --git a/code2/grime/dynamic_array.odin b/code2/grime/dynamic_array.odin index 6e9459b..3e1c30e 100644 --- a/code2/grime/dynamic_array.odin +++ b/code2/grime/dynamic_array.odin @@ -5,10 +5,10 @@ Based on gencpp's and thus zpl's Array implementation Made becasue of the map issue with fonts during hot-reload. I didn't want to make the HMapZPL impl with the [dynamic] array for now to isolate the hot-reload issue (when I was diagnoising) -Update 2024-5-26: +Note 2024-5-26: TODO(Ed): Raw_Dynamic_Array is defined within base:runtime/core.odin and exposes what we need for worst case hot-reloads. So its best to go back to regular dynamic arrays at some point. -Update 2025-5-12: +Note 2025-5-12: I can use either... so I'll just keep both */ @@ -33,28 +33,26 @@ array_underlying_slice :: proc(s: []($ Type)) -> Array(Type) { array_to_slice :: #force_inline proc "contextless" ( using self : Array($ Type) ) -> []Type { return slice( data, int(num)) } array_to_slice_capacity :: #force_inline proc "contextless" ( using self : Array($ Type) ) -> []Type { return slice( data, int(capacity)) } -array_grow_formula :: #force_inline proc "contextless" (value: int) -> int { return (2 * value) + 8 } +array_grow_formula :: #force_inline proc "contextless" (value: int) -> int { return (2 * value) + 8 } +array_block_size :: #force_inline proc "contextless" (self: Array($Type)) -> int { return size_of(ArrayHeader(Type)) + self.capacity * size_of(Type) } //region Lifetime & Memory Resize Operations array_init :: proc( $Array_Type : typeid / Array($Type), capacity: int, - allocator := context.allocator, fixed_cap: b64 = false, dbg_name: string = "" + allocator := context.allocator, fixed_cap: bool = false, dbg_name: string = "" ) -> (result: Array(Type), alloc_error: AllocatorError) { - header_size := size_of(ArrayHeader(Type)) - array_size := header_size + int(capacity) * size_of(Type) - + array_size := size_of(ArrayHeader(Type)) + int(capacity) * size_of(Type) raw_mem: []byte raw_mem, alloc_error = mem_alloc(array_size, ainfo = allocator) // log( str_fmt_tmp("array reserved: %d", header_size + int(capacity) * size_of(Type) )) if alloc_error != AllocatorError.None do return - - result.header = cast( ^ArrayHeader(Type)) cursor(raw_mem) + result.header = transmute( ^ArrayHeader(Type)) cursor(raw_mem) result.backing = allocator result.dbg_name = dbg_name - result.fixed_cap = fixed_cap + result.fixed_cap = cast(b64) fixed_cap result.capacity = capacity - result.data = cast( [^]Type ) (cast( [^]ArrayHeader(Type)) result.header)[ 1:] + result.data = transmute( [^]Type ) (transmute( [^]ArrayHeader(Type)) result.header)[ 1:] return } array_free :: proc(self: Array($Type)) { @@ -81,11 +79,9 @@ array_set_capacity :: proc( self : ^Array( $ Type ), new_capacity: int) -> Alloc header_size :: size_of(ArrayHeader(Type)) new_size := header_size + new_capacity * size_of(Type) old_size := header_size + self.capacity * size_of(Type) - // TODO(Ed): You were here.. - new_mem, result_code := resize_non_zeroed( self.header, old_size, new_size, mem.DEFAULT_ALIGNMENT, allocator = self.backing ) - if result_code != AllocatorError.None { - ensure( false, "Failed to allocate for new array capacity" ) - log_print( "Failed to allocate for new array capacity", level = LogLevel.Warning ) + new_mem, result_code := mem_resize( slice(transmute(^u8)self.header, old_size), new_size, MEMORY_ALIGNMENT_DEFAULT, ainfo = self.backing ) + if ensure( result_code != AllocatorError.None, "Failed to allocate for new array capacity" ) { + log_print( "Failed to allocate for new array capacity", level = LoggerLevel.Warning ) return result_code } if new_mem == nil { ensure(false, "new_mem is nil but no allocation error"); return result_code } @@ -128,23 +124,7 @@ array_append_value :: proc(self: ^Array($Type), value: Type) -> AllocatorError { self.header.num += 1 return AllocatorError.None } -array_append_at_value :: proc(self : ^Array($Type), item: Type, id: int) -> AllocatorError { - ensure(id < self.num, "Why are we doing an append at beyond the bounds of the current element count") - id := id; { - // TODO(Ed): Not sure I want this... - if id >= self.num do id = self.num - if id < 0 do id = 0 - } - if self.capacity < self.num + 1 { - grow_result := array_grow( self, self.capacity ) - if grow_result != AllocatorError.None do return grow_result - } - // libc.memmove( ptr_offset(target, 1), target, uint(num - id) * size_of(Type) ) - copy(self.data[id + 1:], self.data[id], uint(self.num - id) * size_of(Type)) - self.data[id] = item - self.num += 1 - return AllocatorError.None -} + // Asumes non-overlapping for items. array_append_at_slice :: proc(self : ^Array($Type ), items: []Type, id: int) -> AllocatorError { @@ -162,15 +142,31 @@ array_append_at_slice :: proc(self : ^Array($Type ), items: []Type, id: int) -> self.num += len(items) return AllocatorError.None } +array_append_at_value :: proc(self: ^Array($Type), item: Type, id: int) -> AllocatorError { + ensure(id < self.num, "Why are we doing an append at beyond the bounds of the current element count") + id := id; { + // TODO(Ed): Not sure I want this... + if id >= self.num do id = self.num + if id < 0 do id = 0 + } + if self.capacity < self.num + 1 { + grow_result := array_grow( self, self.capacity ) + if grow_result != AllocatorError.None do return grow_result + } + mem_copy(self.data[id + 1:], self.data[id:], int(self.num - id) * size_of(Type)) + self.data[id] = item + self.num += 1 + return AllocatorError.None +} -array_back :: #force_inline proc "contextless" ( self : Array($Type) ) -> Type { assert(self.num > 0); return self.data[self.num - 1] } +array_back :: #force_inline proc "contextless" (self : Array($Type)) -> Type { assert(self.num > 0); return self.data[self.num - 1] } -array_clear :: #force_inline proc "contextless" (self: Array($Type), zero_data: b32 = false) { +array_clear :: #force_inline proc "contextless" (self: Array($Type), zero_data: bool = false) { if zero_data do zero(self.data, int(self.num) * size_of(Type)) self.num = 0 } -array_fill :: proc(self: Array($Type), begin, end: u64, value: Type) -> b32 { +array_fill :: proc(self: Array($Type), begin, end: u64, value: Type) -> bool { ensure(end - begin <= num) ensure(end <= num) if (end - begin > num) || (end > num) do return false @@ -179,7 +175,7 @@ array_fill :: proc(self: Array($Type), begin, end: u64, value: Type) -> b32 { } // Will push value into the array (will not grow if at capacity, use append instead for when that matters) -array_push_back :: #force_inline proc "contextless" (self: Array($Type)) -> b32 { +array_push_back :: #force_inline proc "contextless" (self: Array($Type)) -> bool { if self.num == self.capacity { return false } self.data[self.num] = value self.num += 1 @@ -187,7 +183,7 @@ array_push_back :: #force_inline proc "contextless" (self: Array($Type)) -> b32 } array_remove_at :: proc(self: Array($Type), id: int) { - verify( id < header.num, "Attempted to remove from an index larger than the array" ) - mem_copy(self.data[id], self.data[id + 1], (self.num - id) * size_of(Type)) + verify( id < self.num, "Attempted to remove from an index larger than the array" ) + mem_copy(self.data[id:], self.data[id + 1:], (self.num - id) * size_of(Type)) self.num -= 1 } diff --git a/code2/grime/pkg_mappings.odin b/code2/grime/pkg_mappings.odin index e87b9f5..b676672 100644 --- a/code2/grime/pkg_mappings.odin +++ b/code2/grime/pkg_mappings.odin @@ -124,7 +124,7 @@ array_append :: proc { } array_append_at :: proc { - array_append_at_array, + // array_append_at_array, array_append_at_slice, array_append_at_value, }