From 6fe2df1d7d785a7d56094943851476497f18045d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 30 May 2023 23:42:21 +0100 Subject: [PATCH] Add more documentation to numerous `@builtin` procedures in package runtime --- core/runtime/core_builtin.odin | 116 +++++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 6 deletions(-) diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin index f578a641e..c5cb8cc07 100644 --- a/core/runtime/core_builtin.odin +++ b/core/runtime/core_builtin.odin @@ -27,6 +27,11 @@ init_global_temporary_allocator :: proc(size: int, backup_allocator := context.a } +// `copy_slice` is a built-in procedure that copies elements from a source slice `src` to a destination slice `dst`. +// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum +// of len(src) and len(dst). +// +// Prefer the procedure group `copy`. @builtin copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int { n := max(0, min(len(dst), len(src))) @@ -35,6 +40,11 @@ copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int { } return n } +// `copy_from_string` is a built-in procedure that copies elements from a source slice `src` to a destination string `dst`. +// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum +// of len(src) and len(dst). +// +// Prefer the procedure group `copy`. @builtin copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int { n := max(0, min(len(dst), len(src))) @@ -43,11 +53,20 @@ copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int } return n } +// `copy` is a built-in procedure that copies elements from a source slice `src` to a destination slice/string `dst`. +// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum +// of len(src) and len(dst). @builtin copy :: proc{copy_slice, copy_from_string} +// `unordered_remove` removed the element at the specified `index`. It does so by replacing the current end value +// with the old value, and reducing the length of the dynamic array by 1. +// +// Note: This is an O(1) operation. +// Note: If you the elements to remain in their order, use `ordered_remove`. +// Note: If the index is out of bounds, this procedure will panic. @builtin unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check { bounds_check_error_loc(loc, index, len(array)) @@ -57,7 +76,11 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca } (^Raw_Dynamic_Array)(array).len -= 1 } - +// `ordered_remove` removed the element at the specified `index` whilst keeping the order of the other elements. +// +// Note: This is an O(N) operation. +// Note: If you the elements do not have to remain in their order, prefer `unordered_remove`. +// Note: If the index is out of bounds, this procedure will panic. @builtin ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check { bounds_check_error_loc(loc, index, len(array)) @@ -67,6 +90,10 @@ ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_locati (^Raw_Dynamic_Array)(array).len -= 1 } +// `remove_range` removes a range of elements specified by the range `lo` and `hi`, whilst keeping the order of the other elements. +// +// Note: This is an O(N) operation. +// Note: If the range is out of bounds, this procedure will panic. @builtin remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_location) #no_bounds_check { slice_expr_error_lo_hi_loc(loc, lo, hi, len(array)) @@ -80,6 +107,9 @@ remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_locatio } +// `pop` will remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. +// +// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic. @builtin pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { assert(len(array) > 0, "", loc) @@ -89,6 +119,8 @@ pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bou } +// `pop_safe` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1. +// If the operation is not possible, it will return false. @builtin pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check { if len(array) == 0 { @@ -99,6 +131,9 @@ pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check return } +// `pop_front` will remove and return the first value of dynamic array `array` and reduces the length of `array` by 1. +// +// Note: If the dynamic array as no elements (`len(array) == 0`), this procedure will panic. @builtin pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bounds_check { assert(len(array) > 0, "", loc) @@ -110,6 +145,8 @@ pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) # return res } +// `pop_front_safe` trys to return and remove the first value of dynamic array `array` and reduces the length of `array` by 1. +// If the operation is not possible, it will return false. @builtin pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check { if len(array) == 0 { @@ -124,12 +161,15 @@ pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_ } +// `clear` will set the length of a passed dynamic array or map to `0` @builtin clear :: proc{clear_dynamic_array, clear_map} +// `reserve` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`). @builtin reserve :: proc{reserve_dynamic_array, reserve_map} +// `resize` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`). @builtin resize :: proc{resize_dynamic_array} @@ -137,36 +177,56 @@ resize :: proc{resize_dynamic_array} @builtin shrink :: proc{shrink_dynamic_array, shrink_map} +// `free` will try to free the passed pointer, with the given `allocator` if the allocator supports this operation. @builtin free :: proc{mem_free} +// `free_all` will try to free/reset all of the memory of the given `allocator` if the allocator supports this operation. @builtin free_all :: proc{mem_free_all} +// `delete_string` will try to free the underlying data of the passed string, with the given `allocator` if the allocator supports this operation. +// +// Note: Prefer the procedure group `delete`. @builtin delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { return mem_free_with_size(raw_data(str), len(str), allocator, loc) } +// `delete_cstring` will try to free the underlying data of the passed string, with the given `allocator` if the allocator supports this operation. +// +// Note: Prefer the procedure group `delete`. @builtin delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { return mem_free((^byte)(str), allocator, loc) } +// `delete_dynamic_array` will try to free the underlying data of the passed dynamic array, with the given `allocator` if the allocator supports this operation. +// +// Note: Prefer the procedure group `delete`. @builtin delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error { return mem_free_with_size(raw_data(array), cap(array)*size_of(E), array.allocator, loc) } +// `delete_slice` will try to free the underlying data of the passed sliced, with the given `allocator` if the allocator supports this operation. +// +// Note: Prefer the procedure group `delete`. @builtin delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { return mem_free_with_size(raw_data(array), len(array)*size_of(E), allocator, loc) } +// `delete_map` will try to free the underlying data of the passed map, with the given `allocator` if the allocator supports this operation. +// +// Note: Prefer the procedure group `delete`. @builtin delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error { return map_free_dynamic(transmute(Raw_Map)m, map_info(T), loc) } +// `delete` will try to free the underlying data of the passed built-in data structure (string, cstring, dynamic array, slice, or map), with the given `allocator` if the allocator supports this operation. +// +// Note: Prefer `delete` over the specific `delete_*` procedures where possible. @builtin delete :: proc{ delete_string, @@ -213,18 +273,34 @@ make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocat return transmute(T)s, err } +// `make_slice` allocates and initializes a slice. Like `new`, the first argument is a type, not a value. +// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. +// +// Note: Prefer using the procedure group `make`. @(builtin, require_results) make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error { return make_aligned(T, len, align_of(E), allocator, loc) } +// `make_dynamic_array` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value. +// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. +// +// Note: Prefer using the procedure group `make`. @(builtin, require_results) make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error { return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc) } +// `make_dynamic_array_len` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value. +// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. +// +// Note: Prefer using the procedure group `make`. @(builtin, require_results) make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error { return make_dynamic_array_len_cap(T, len, len, allocator, loc) } +// `make_dynamic_array_len_cap` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value. +// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. +// +// Note: Prefer using the procedure group `make`. @(builtin, require_results) make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error { make_dynamic_array_error_loc(loc, len, cap) @@ -236,6 +312,10 @@ make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #a array = transmute(T)s return } +// `make_map` allocates and initializes a dynamic array. Like `new`, the first argument is a type, not a value. +// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. +// +// Note: Prefer using the procedure group `make`. @(builtin, require_results) make_map :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1< (m: T, err: Allocator_Error) #optional_allocator_error { make_map_expr_error_loc(loc, capacity) @@ -244,6 +324,12 @@ make_map :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1< (mp: T, err: Allocator_Error) #optional_allocator_error { make_slice_error_loc(loc, len) @@ -256,8 +342,9 @@ make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := con } -// The make built-in procedure allocates and initializes a value of type slice, dynamic array, or map (only) -// Similar to new, the first argument is a type, not a value. Unlike new, make's return type is the same as the +// `make` built-in procedure allocates and initializes a value of type slice, dynamic array, map, or multi-pointer (only). +// +// Similar to `new`, the first argument is a type, not a value. Unlike new, make's return type is the same as the // type of its argument, not a pointer to it. // Make uses the specified allocator, default is context.allocator, default is context.allocator @builtin @@ -272,6 +359,9 @@ make :: proc{ +// `clear_map` will set the length of a passed map to `0` +// +// Note: Prefer the procedure group `clear` @builtin clear_map :: proc "contextless" (m: ^$T/map[$K]$V) { if m == nil { @@ -280,14 +370,17 @@ clear_map :: proc "contextless" (m: ^$T/map[$K]$V) { map_clear_dynamic((^Raw_Map)(m), map_info(T)) } +// `reserve_map` will try to reserve memory of a passed map to the requested element count (setting the `cap`). +// +// Note: Prefer the procedure group `reserve` @builtin reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int, loc := #caller_location) -> Allocator_Error { return __dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc) if m != nil else nil } -/* - Shrinks the capacity of a map down to the current length. -*/ +// Shrinks the capacity of a map down to the current length. +// +// Note: Prefer the procedure group `shrink` @builtin shrink_map :: proc(m: ^$T/map[$K]$V, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) { if m != nil { @@ -526,6 +619,9 @@ assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string +// `clear_dynamic_array` will set the length of a passed dynamic array to `0` +// +// Note: Prefer the procedure group `clear`. @builtin clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) { if array != nil { @@ -533,6 +629,9 @@ clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) { } } +// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`). +// +// Note: Prefer the procedure group `reserve`. @builtin reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error { if array == nil { @@ -563,6 +662,9 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal return nil } +// `resize_dynamic_array` will try to resize memory of a passed dynamic array or map to the requested element count (setting the `len`, and possibly `cap`). +// +// Note: Prefer the procedure group `resize` @builtin resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error { if array == nil { @@ -603,6 +705,8 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller Returns false if `cap(array) < new_cap`, or the allocator report failure. If `len(array) < new_cap`, then `len(array)` will be left unchanged. + + Note: Prefer the procedure group `shrink` */ shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) { if array == nil {