mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
@@ -138,10 +138,13 @@ type_is_rune :: proc($T: typeid) -> bool ---
|
||||
type_is_float :: proc($T: typeid) -> bool ---
|
||||
type_is_complex :: proc($T: typeid) -> bool ---
|
||||
type_is_quaternion :: proc($T: typeid) -> bool ---
|
||||
type_is_string :: proc($T: typeid) -> bool ---
|
||||
type_is_typeid :: proc($T: typeid) -> bool ---
|
||||
type_is_any :: proc($T: typeid) -> bool ---
|
||||
type_is_string :: proc($T: typeid) -> bool ---
|
||||
type_is_string16 :: proc($T: typeid) -> bool ---
|
||||
type_is_cstring :: proc($T: typeid) -> bool ---
|
||||
type_is_cstring16 :: proc($T: typeid) -> bool ---
|
||||
|
||||
|
||||
type_is_endian_platform :: proc($T: typeid) -> bool ---
|
||||
type_is_endian_little :: proc($T: typeid) -> bool ---
|
||||
@@ -154,6 +157,7 @@ type_is_indexable :: proc($T: typeid) -> bool ---
|
||||
type_is_sliceable :: proc($T: typeid) -> bool ---
|
||||
type_is_comparable :: proc($T: typeid) -> bool ---
|
||||
type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=)
|
||||
type_is_nearly_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (including floats)
|
||||
type_is_dereferenceable :: proc($T: typeid) -> bool ---
|
||||
type_is_valid_map_key :: proc($T: typeid) -> bool ---
|
||||
type_is_valid_matrix_elements :: proc($T: typeid) -> bool ---
|
||||
@@ -344,6 +348,9 @@ simd_lanes_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
|
||||
has_target_feature :: proc($test: $T) -> bool where type_is_string(T) || type_is_proc(T) ---
|
||||
|
||||
|
||||
// Utility Calls
|
||||
concatentate :: proc(x, y: $T, z: ..T) -> T where type_is_array(T) || type_is_slice(T) ---
|
||||
|
||||
// Returns the value of the procedure where `x` must be a call expression
|
||||
procedure_of :: proc(x: $T) -> T where type_is_proc(T) ---
|
||||
|
||||
@@ -374,10 +381,11 @@ objc_selector :: struct{}
|
||||
objc_class :: struct{}
|
||||
objc_ivar :: struct{}
|
||||
|
||||
objc_id :: ^objc_object
|
||||
objc_SEL :: ^objc_selector
|
||||
objc_Class :: ^objc_class
|
||||
objc_Ivar :: ^objc_ivar
|
||||
objc_id :: ^objc_object
|
||||
objc_SEL :: ^objc_selector
|
||||
objc_Class :: ^objc_class
|
||||
objc_Ivar :: ^objc_ivar
|
||||
objc_instancetype :: distinct objc_id
|
||||
|
||||
objc_find_selector :: proc($name: string) -> objc_SEL ---
|
||||
objc_register_selector :: proc($name: string) -> objc_SEL ---
|
||||
@@ -385,6 +393,7 @@ objc_find_class :: proc($name: string) -> objc_Class ---
|
||||
objc_register_class :: proc($name: string) -> objc_Class ---
|
||||
objc_ivar_get :: proc(self: ^$T) -> ^$U ---
|
||||
objc_block :: proc(invoke: $T, ..any) -> ^Objc_Block(T) where type_is_proc(T) ---
|
||||
objc_super :: proc(obj: ^$T) -> ^$U where type_is_subtype_of(T, objc_object) && type_is_subtype_of(U, objc_object) ---
|
||||
|
||||
valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr ---
|
||||
|
||||
|
||||
@@ -636,6 +636,8 @@ _cleanup_runtime_contextless :: proc "contextless" () {
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
// type_info_base returns the base-type of a `^Type_Info` stripping the `distinct`ness from the first level
|
||||
@(require_results)
|
||||
type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil {
|
||||
return nil
|
||||
@@ -652,6 +654,10 @@ type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
}
|
||||
|
||||
|
||||
// type_info_core returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR
|
||||
// returns the backing integer type of an enum or bit_set `^Type_Info`.
|
||||
// This is also aliased as `type_info_base_without_enum`
|
||||
@(require_results)
|
||||
type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil {
|
||||
return nil
|
||||
@@ -668,6 +674,10 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
// type_info_base_without_enum returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR
|
||||
// returns the backing integer type of an enum or bit_set `^Type_Info`.
|
||||
// This is also aliased as `type_info_core`
|
||||
type_info_base_without_enum :: type_info_core
|
||||
|
||||
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check {
|
||||
@@ -684,15 +694,23 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check
|
||||
}
|
||||
|
||||
when !ODIN_NO_RTTI {
|
||||
// typeid_base returns the base-type of a `typeid` stripping the `distinct`ness from the first level
|
||||
typeid_base :: proc "contextless" (id: typeid) -> typeid {
|
||||
ti := type_info_of(id)
|
||||
ti = type_info_base(ti)
|
||||
return ti.id
|
||||
}
|
||||
// typeid_core returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR
|
||||
// returns the backing integer type of an enum or bit_set `typeid`.
|
||||
// This is also aliased as `typeid_base_without_enum`
|
||||
typeid_core :: proc "contextless" (id: typeid) -> typeid {
|
||||
ti := type_info_core(type_info_of(id))
|
||||
return ti.id
|
||||
}
|
||||
|
||||
// typeid_base_without_enum returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR
|
||||
// returns the backing integer type of an enum or bit_set `typeid`.
|
||||
// This is also aliased as `typeid_core`
|
||||
typeid_base_without_enum :: typeid_core
|
||||
}
|
||||
|
||||
@@ -708,11 +726,15 @@ default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, opt
|
||||
// Nothing
|
||||
}
|
||||
|
||||
// Returns the default logger used by `context.logger`
|
||||
@(require_results)
|
||||
default_logger :: proc() -> Logger {
|
||||
return Logger{default_logger_proc, nil, Logger_Level.Debug, nil}
|
||||
}
|
||||
|
||||
|
||||
// Returns the default `context`
|
||||
@(require_results)
|
||||
default_context :: proc "contextless" () -> Context {
|
||||
c: Context
|
||||
__init_context(&c)
|
||||
|
||||
@@ -62,6 +62,8 @@ when !NO_DEFAULT_TEMP_ALLOCATOR {
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes the global temporary allocator used as the default `context.temp_allocator`.
|
||||
// This is ignored when `NO_DEFAULT_TEMP_ALLOCATOR` is true.
|
||||
@(builtin, disabled=NO_DEFAULT_TEMP_ALLOCATOR)
|
||||
init_global_temporary_allocator :: proc(size: int, backup_allocator := context.allocator) {
|
||||
when !NO_DEFAULT_TEMP_ALLOCATOR {
|
||||
@@ -565,6 +567,7 @@ _append_elem :: #force_no_inline proc(array: ^Raw_Dynamic_Array, size_of_elem, a
|
||||
return
|
||||
}
|
||||
|
||||
// `append_elem` appends an element to the end of a dynamic array.
|
||||
@builtin
|
||||
append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
when size_of(E) == 0 {
|
||||
@@ -576,6 +579,9 @@ append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller
|
||||
}
|
||||
}
|
||||
|
||||
// `non_zero_append_elem` appends an element to the end of a dynamic array, without zeroing any reserved memory
|
||||
//
|
||||
// Note: Prefer using the procedure group `non_zero_append
|
||||
@builtin
|
||||
non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
when size_of(E) == 0 {
|
||||
@@ -614,6 +620,9 @@ _append_elems :: #force_no_inline proc(array: ^Raw_Dynamic_Array, size_of_elem,
|
||||
return arg_len, err
|
||||
}
|
||||
|
||||
// `append_elems` appends `args` to the end of a dynamic array.
|
||||
//
|
||||
// Note: Prefer using the procedure group `append`.
|
||||
@builtin
|
||||
append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
when size_of(E) == 0 {
|
||||
@@ -625,6 +634,9 @@ append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #ca
|
||||
}
|
||||
}
|
||||
|
||||
// `non_zero_append_elems` appends `args` to the end of a dynamic array, without zeroing any reserved memory
|
||||
//
|
||||
// Note: Prefer using the procedure group `non_zero_append
|
||||
@builtin
|
||||
non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, #no_broadcast args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
when size_of(E) == 0 {
|
||||
@@ -641,10 +653,16 @@ _append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, should_ze
|
||||
return _append_elems((^Raw_Dynamic_Array)(array), 1, 1, should_zero, loc, raw_data(arg), len(arg))
|
||||
}
|
||||
|
||||
// `append_elem_string` appends a string to the end of a dynamic array of bytes
|
||||
//
|
||||
// Note: Prefer using the procedure group `append`.
|
||||
@builtin
|
||||
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
return _append_elem_string(array, arg, true, loc)
|
||||
}
|
||||
// `non_zero_append_elem_string` appends a string to the end of a dynamic array of bytes, without zeroing any reserved memory
|
||||
//
|
||||
// Note: Prefer using the procedure group `non_zero_append`.
|
||||
@builtin
|
||||
non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
return _append_elem_string(array, arg, false, loc)
|
||||
@@ -652,6 +670,8 @@ non_zero_append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, l
|
||||
|
||||
|
||||
// The append_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type
|
||||
//
|
||||
// Note: Prefer using the procedure group `append`.
|
||||
@builtin
|
||||
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
n_arg: int
|
||||
@@ -666,7 +686,8 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
|
||||
}
|
||||
|
||||
// The append built-in procedure appends elements to the end of a dynamic array
|
||||
@builtin append :: proc{
|
||||
@builtin
|
||||
append :: proc{
|
||||
append_elem,
|
||||
append_elems,
|
||||
append_elem_string,
|
||||
@@ -675,7 +696,8 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
|
||||
append_soa_elems,
|
||||
}
|
||||
|
||||
@builtin non_zero_append :: proc{
|
||||
@builtin
|
||||
non_zero_append :: proc{
|
||||
non_zero_append_elem,
|
||||
non_zero_append_elems,
|
||||
non_zero_append_elem_string,
|
||||
@@ -685,6 +707,8 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
|
||||
}
|
||||
|
||||
|
||||
// `append_nothing` appends an empty value to a dynamic array. It returns `1, nil` if successful, and `0, err` when it was not possible,
|
||||
// whatever `err` happens to be.
|
||||
@builtin
|
||||
append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
if array == nil {
|
||||
@@ -696,6 +720,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: i
|
||||
}
|
||||
|
||||
|
||||
// `inject_at_elem` injects an element in a dynamic array at a specified index and moves the previous elements after that index "across"
|
||||
@builtin
|
||||
inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
when !ODIN_NO_BOUNDS_CHECK {
|
||||
@@ -717,6 +742,7 @@ inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcas
|
||||
return
|
||||
}
|
||||
|
||||
// `inject_at_elems` injects multiple elements in a dynamic array at a specified index and moves the previous elements after that index "across"
|
||||
@builtin
|
||||
inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
when !ODIN_NO_BOUNDS_CHECK {
|
||||
@@ -743,6 +769,7 @@ inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadca
|
||||
return
|
||||
}
|
||||
|
||||
// `inject_at_elem_string` injects a string into a dynamic array at a specified index and moves the previous elements after that index "across"
|
||||
@builtin
|
||||
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
when !ODIN_NO_BOUNDS_CHECK {
|
||||
@@ -767,10 +794,13 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, ar
|
||||
return
|
||||
}
|
||||
|
||||
// `inject_at` injects something into a dynamic array at a specified index and moves the previous elements after that index "across"
|
||||
@builtin inject_at :: proc{inject_at_elem, inject_at_elems, inject_at_elem_string}
|
||||
|
||||
|
||||
|
||||
// `assign_at_elem` assigns a value at a given index. If the requested index is smaller than the current
|
||||
// size of the dynamic array, it will attempt to `resize` the a new length of `index+1` and then assign as `index`.
|
||||
@builtin
|
||||
assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
if index < len(array) {
|
||||
@@ -785,6 +815,8 @@ assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc
|
||||
}
|
||||
|
||||
|
||||
// `assign_at_elems` assigns a values at a given index. If the requested index is smaller than the current
|
||||
// size of the dynamic array, it will attempt to `resize` the a new length of `index+len(args)` and then assign as `index`.
|
||||
@builtin
|
||||
assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
new_size := index + len(args)
|
||||
@@ -801,7 +833,8 @@ assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadca
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// `assign_at_elem_string` assigns a string at a given index. If the requested index is smaller than the current
|
||||
// size of the dynamic array, it will attempt to `resize` the a new length of `index+len(arg)` and then assign as `index`.
|
||||
@builtin
|
||||
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
new_size := index + len(arg)
|
||||
@@ -818,7 +851,14 @@ assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, ar
|
||||
return
|
||||
}
|
||||
|
||||
@builtin assign_at :: proc{assign_at_elem, assign_at_elems, assign_at_elem_string}
|
||||
// `assign_at` assigns a value at a given index. If the requested index is smaller than the current
|
||||
// size of the dynamic array, it will attempt to `resize` the a new length of `index+size_needed` and then assign as `index`.
|
||||
@builtin
|
||||
assign_at :: proc{
|
||||
assign_at_elem,
|
||||
assign_at_elems,
|
||||
assign_at_elem_string,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -835,6 +875,8 @@ 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`).
|
||||
//
|
||||
// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`).
|
||||
//
|
||||
// Note: Prefer the procedure group `reserve`.
|
||||
_reserve_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_elem, align_of_elem: int, capacity: int, should_zero: bool, loc := #caller_location) -> Allocator_Error {
|
||||
if a == nil {
|
||||
@@ -870,11 +912,21 @@ _reserve_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_e
|
||||
return nil
|
||||
}
|
||||
|
||||
// `reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
||||
//
|
||||
// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`).
|
||||
//
|
||||
// Note: Prefer the procedure group `reserve`.
|
||||
@builtin
|
||||
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||
return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, true, loc)
|
||||
}
|
||||
|
||||
// `non_zero_reserve_dynamic_array` will try to reserve memory of a passed dynamic array or map to the requested element count (setting the `cap`).
|
||||
//
|
||||
// When a memory resize allocation is required, the memory will be asked to not be zeroed (i.e. it calls `non_zero_mem_resize`).
|
||||
//
|
||||
// Note: Prefer the procedure group `non_zero_reserve`.
|
||||
@builtin
|
||||
non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||
return _reserve_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), capacity, false, loc)
|
||||
@@ -924,28 +976,33 @@ _resize_dynamic_array :: #force_no_inline proc(a: ^Raw_Dynamic_Array, size_of_el
|
||||
|
||||
// `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`).
|
||||
//
|
||||
// When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls `mem_resize`).
|
||||
//
|
||||
// Note: Prefer the procedure group `resize`
|
||||
@builtin
|
||||
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
|
||||
return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, true, loc=loc)
|
||||
}
|
||||
|
||||
// `non_zero_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`).
|
||||
//
|
||||
// When a memory resize allocation is required, the memory will be asked to not be zeroed (i.e. it calls `non_zero_mem_resize`).
|
||||
//
|
||||
// Note: Prefer the procedure group `non_zero_resize`
|
||||
@builtin
|
||||
non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
|
||||
return _resize_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), length, false, loc=loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
|
||||
|
||||
If `new_cap` is negative, then `len(array)` is used.
|
||||
|
||||
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`
|
||||
*/
|
||||
// Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
|
||||
//
|
||||
// If `new_cap` is negative, then `len(array)` is used.
|
||||
//
|
||||
// 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, #any_int new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
|
||||
return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc)
|
||||
}
|
||||
@@ -1027,6 +1084,7 @@ map_entry :: proc(m: ^$T/map[$K]$V, key: K, loc := #caller_location) -> (key_ptr
|
||||
}
|
||||
|
||||
|
||||
// `card` returns the number of bits that are set in a bit_set—its cardinality
|
||||
@builtin
|
||||
card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
||||
return int(intrinsics.count_ones(transmute(intrinsics.type_bit_set_underlying_type(S))s))
|
||||
@@ -1034,6 +1092,10 @@ card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
||||
|
||||
|
||||
|
||||
// Evaluates the condition and panics the program iff the condition is false.
|
||||
// This uses the `context.assertion_failure_procedure` to assert.
|
||||
//
|
||||
// This routine will be ignored when `ODIN_DISABLE_ASSERT` is true.
|
||||
@builtin
|
||||
@(disabled=ODIN_DISABLE_ASSERT)
|
||||
assert :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||
@@ -1054,9 +1116,9 @@ assert :: proc(condition: bool, message := #caller_expression(condition), loc :=
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluates the condition and aborts the program iff the condition is
|
||||
// false. This routine ignores `ODIN_DISABLE_ASSERT`, and will always
|
||||
// execute.
|
||||
// Evaluates the condition and panics the program iff the condition is false.
|
||||
// This uses the `context.assertion_failure_procedure` to assert.
|
||||
// This routine ignores `ODIN_DISABLE_ASSERT`, and will always execute.
|
||||
@builtin
|
||||
ensure :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||
if !condition {
|
||||
@@ -1072,6 +1134,8 @@ ensure :: proc(condition: bool, message := #caller_expression(condition), loc :=
|
||||
}
|
||||
}
|
||||
|
||||
// Panics the program with a message.
|
||||
// This uses the `context.assertion_failure_procedure` to panic.
|
||||
@builtin
|
||||
panic :: proc(message: string, loc := #caller_location) -> ! {
|
||||
p := context.assertion_failure_proc
|
||||
@@ -1081,6 +1145,8 @@ panic :: proc(message: string, loc := #caller_location) -> ! {
|
||||
p("panic", message, loc)
|
||||
}
|
||||
|
||||
// Panics the program with a message to indicate something has yet to be implemented.
|
||||
// This uses the `context.assertion_failure_procedure` to assert.
|
||||
@builtin
|
||||
unimplemented :: proc(message := "", loc := #caller_location) -> ! {
|
||||
p := context.assertion_failure_proc
|
||||
@@ -1090,7 +1156,10 @@ unimplemented :: proc(message := "", loc := #caller_location) -> ! {
|
||||
p("not yet implemented", message, loc)
|
||||
}
|
||||
|
||||
|
||||
// Evaluates the condition and panics the program iff the condition is false.
|
||||
// This uses the `default_assertion_contextless_failure_proc` to assert.
|
||||
//
|
||||
// This routine will be ignored when `ODIN_DISABLE_ASSERT` is true.
|
||||
@builtin
|
||||
@(disabled=ODIN_DISABLE_ASSERT)
|
||||
assert_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||
@@ -1107,6 +1176,8 @@ assert_contextless :: proc "contextless" (condition: bool, message := #caller_ex
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluates the condition and panics the program iff the condition is false.
|
||||
// This uses the `default_assertion_contextless_failure_proc` to assert.
|
||||
@builtin
|
||||
ensure_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||
if !condition {
|
||||
@@ -1118,11 +1189,15 @@ ensure_contextless :: proc "contextless" (condition: bool, message := #caller_ex
|
||||
}
|
||||
}
|
||||
|
||||
// Panics the program with a message to indicate something has yet to be implemented.
|
||||
// This uses the `default_assertion_contextless_failure_proc` to assert.
|
||||
@builtin
|
||||
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {
|
||||
default_assertion_contextless_failure_proc("panic", message, loc)
|
||||
}
|
||||
|
||||
// Panics the program with a message.
|
||||
// This uses the `default_assertion_contextless_failure_proc` to assert.
|
||||
@builtin
|
||||
unimplemented_contextless :: proc "contextless" (message := "", loc := #caller_location) -> ! {
|
||||
default_assertion_contextless_failure_proc("not yet implemented", message, loc)
|
||||
|
||||
@@ -23,6 +23,14 @@ nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
return nil, .None
|
||||
}
|
||||
|
||||
// nil_allocator returns an allocator which will return `nil` for any result.
|
||||
// * `.Alloc`, `.Alloc_Non_Zero`, `.Resize`, `.Resize_Non_Zeroed` will return `nil, .Out_Of_Memory`
|
||||
// * `.Free` will return `nil, .None`
|
||||
// * `.Free_All` will return `nil, .Mode_Not_Implemented`
|
||||
// * `.Query_Features`, `.Query_Info` will return `nil, .Mode_Not_Implemented`
|
||||
//
|
||||
// This is extremely useful for creating a dynamic array from a buffer which does not nothing
|
||||
// on a resize/reserve beyond the originally allocated memory.
|
||||
@(require_results)
|
||||
nil_allocator :: proc "contextless" () -> Allocator {
|
||||
return Allocator{
|
||||
@@ -73,6 +81,9 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// panic_allocator returns an allocator which will panic for any non-zero-sized allocation or `query_info`
|
||||
//
|
||||
// This is extremely useful for to check when something does a memory operation when it should not, and thus panic.
|
||||
@(require_results)
|
||||
panic_allocator :: proc() -> Allocator {
|
||||
return Allocator{
|
||||
|
||||
@@ -4,6 +4,7 @@ DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKIN
|
||||
NO_DEFAULT_TEMP_ALLOCATOR: bool : ODIN_OS == .Freestanding || ODIN_DEFAULT_TO_NIL_ALLOCATOR
|
||||
|
||||
when NO_DEFAULT_TEMP_ALLOCATOR {
|
||||
// `Default_Temp_Allocator` is a `nil_allocator` when `NO_DEFAULT_TEMP_ALLOCATOR` is `true`.
|
||||
Default_Temp_Allocator :: struct {}
|
||||
|
||||
default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator := context.allocator) {}
|
||||
@@ -20,6 +21,11 @@ when NO_DEFAULT_TEMP_ALLOCATOR {
|
||||
default_temp_allocator_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) {
|
||||
}
|
||||
} else {
|
||||
// `Default_Temp_Allocator` is an `Arena` based type of allocator. See `runtime.Arena` for its implementation.
|
||||
// The default `context.temp_allocator` is typically called with `free_all(context.temp_allocator)` once per "frame-loop"
|
||||
// to prevent it from "leaking" memory.
|
||||
//
|
||||
// Note: `Default_Temp_Allocator` is a `nil_allocator` when `NO_DEFAULT_TEMP_ALLOCATOR` is `true`.
|
||||
Default_Temp_Allocator :: struct {
|
||||
arena: Arena,
|
||||
}
|
||||
|
||||
@@ -15,16 +15,25 @@ objc_SEL :: ^intrinsics.objc_selector
|
||||
objc_Ivar :: ^intrinsics.objc_ivar
|
||||
objc_BOOL :: bool
|
||||
|
||||
objc_super :: struct {
|
||||
receiver: objc_id,
|
||||
super_class: objc_Class,
|
||||
}
|
||||
|
||||
objc_IMP :: proc "c" (object: objc_id, sel: objc_SEL, #c_vararg args: ..any) -> objc_id
|
||||
|
||||
foreign ObjC {
|
||||
sel_registerName :: proc "c" (name: cstring) -> objc_SEL ---
|
||||
|
||||
objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
|
||||
objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 ---
|
||||
objc_msgSend_fp2ret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> complex128 ---
|
||||
objc_msgSend_stret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
|
||||
objc_msgSend :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
|
||||
objc_msgSend_fpret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> f64 ---
|
||||
objc_msgSend_fp2ret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) -> complex128 ---
|
||||
objc_msgSend_stret :: proc "c" (self: objc_id, op: objc_SEL, #c_vararg args: ..any) ---
|
||||
|
||||
// See: https://github.com/opensource-apple/objc4/blob/cd5e62a5597ea7a31dccef089317abb3a661c154/runtime/objc-abi.h#L111
|
||||
objc_msgSendSuper2 :: proc "c" (super: rawptr, op: objc_SEL, #c_vararg args: ..any) -> objc_id ---
|
||||
objc_msgSendSuper2_stret :: proc "c" (super: ^objc_super, op: objc_SEL, #c_vararg args: ..any) ---
|
||||
|
||||
|
||||
objc_lookUpClass :: proc "c" (name: cstring) -> objc_Class ---
|
||||
objc_allocateClassPair :: proc "c" (superclass: objc_Class, name: cstring, extraBytes: uint) -> objc_Class ---
|
||||
@@ -33,6 +42,7 @@ foreign ObjC {
|
||||
class_addIvar :: proc "c" (cls: objc_Class, name: cstring, size: uint, alignment: u8, types: cstring) -> objc_BOOL ---
|
||||
class_getInstanceVariable :: proc "c" (cls : objc_Class, name: cstring) -> objc_Ivar ---
|
||||
class_getInstanceSize :: proc "c" (cls : objc_Class) -> uint ---
|
||||
class_getSuperclass :: proc "c" (cls : objc_Class) -> objc_Class ---
|
||||
ivar_getOffset :: proc "c" (v: objc_Ivar) -> uintptr ---
|
||||
object_getClass :: proc "c" (obj: objc_id) -> objc_Class ---
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user