Mostly exploring hashtables, some new files...
I made the files for the ast but they're not populated yet. I made some initial implementation for raddbg flavored linked-lists.
This commit is contained in:
		
							
								
								
									
										0
									
								
								code/ast_formatting.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								code/ast_formatting.odin
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								code/ast_text.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								code/ast_text.odin
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								code/ast_whitespace.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								code/ast_whitespace.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -3,6 +3,9 @@ package sectr | ||||
|  | ||||
| import "base:builtin" | ||||
| 	copy :: builtin.copy | ||||
| import "base:intrinsics" | ||||
| 	type_has_field :: intrinsics.type_has_field | ||||
| 	type_elem_type :: intrinsics.type_elem_type | ||||
| import "base:runtime" | ||||
| 	Byte     :: runtime.Byte | ||||
| 	Kilobyte :: runtime.Kilobyte | ||||
| @@ -54,6 +57,19 @@ import str "core:strings" | ||||
| 	str_builder_to_string  :: str.to_string | ||||
| import "core:unicode/utf8" | ||||
|  | ||||
| OS_Type :: type_of(ODIN_OS) | ||||
|  | ||||
| // Alias Tables | ||||
|  | ||||
| get_bounds :: proc { | ||||
| 	box_get_bounds, | ||||
| 	view_get_bounds, | ||||
| } | ||||
|  | ||||
| is_power_of_two :: proc { | ||||
| 	is_power_of_two_u32, | ||||
| } | ||||
|  | ||||
| to_runes :: proc { | ||||
| 	utf8.string_to_runes, | ||||
| } | ||||
| @@ -61,47 +77,3 @@ to_runes :: proc { | ||||
| to_string :: proc { | ||||
| 	str_builder_to_string, | ||||
| } | ||||
|  | ||||
| OS_Type :: type_of(ODIN_OS) | ||||
|  | ||||
| kilobytes :: #force_inline proc "contextless" ( kb : $ integer_type ) -> integer_type { | ||||
| 	return kb * Kilobyte | ||||
| } | ||||
| megabytes :: #force_inline proc "contextless" ( mb : $ integer_type ) -> integer_type { | ||||
| 	return mb * Megabyte | ||||
| } | ||||
| gigabytes  :: #force_inline proc "contextless" ( gb : $ integer_type ) -> integer_type { | ||||
| 	return gb * Gigabyte | ||||
| } | ||||
| terabytes  :: #force_inline proc "contextless" ( tb : $ integer_type ) -> integer_type { | ||||
| 	return tb * Terabyte | ||||
| } | ||||
|  | ||||
| get_bounds :: proc { | ||||
| 	box_get_bounds, | ||||
| 	view_get_bounds, | ||||
| } | ||||
|  | ||||
| // TODO(Ed): Review | ||||
| //region Doubly Linked List generic procs (verbose) | ||||
|  | ||||
| dbl_linked_list_push_back :: proc(first: ^(^ $ Type), last: ^(^ Type), new_node: ^ Type) | ||||
| { | ||||
| 	if first == nil || first^ == nil { | ||||
| 			// List is empty, set first and last to the new node | ||||
| 			(first ^) = new_node | ||||
| 			(last  ^) = new_node | ||||
| 			new_node.next = nil | ||||
| 			new_node.prev = nil | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 			// List is not empty, add new node to the end | ||||
| 			(last^).next = new_node | ||||
| 			new_node.prev = last^ | ||||
| 			(last ^) = new_node | ||||
| 			new_node.next = nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //endregion | ||||
|   | ||||
| @@ -15,9 +15,6 @@ Array :: struct ( $ Type : typeid ) { | ||||
| 	data      : [^]Type, | ||||
| } | ||||
|  | ||||
| // @(private=file) | ||||
| // Array :: Array_ZPL | ||||
|  | ||||
| array_to_slice :: proc( using self : Array( $ Type) ) -> []Type { | ||||
| 	return slice_ptr( data, num ) | ||||
| } | ||||
|   | ||||
							
								
								
									
										27
									
								
								code/grime_hashmap_msi.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								code/grime_hashmap_msi.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| // Mask-Step-Index (MSI) Hash Table implementation. | ||||
| // See: https://nullprogram.com/blog/2022/08/08/ | ||||
| package sectr | ||||
| // TODO(Ed) : This is a wip, I haven't gotten the nuance of this mess down pact. | ||||
|  | ||||
| // Compute a mask, then a step size, and finally an index. | ||||
| // The exponent parameter is a power-of-two exponent for the hash-table size. | ||||
| msi_hmap_lookup :: proc ( hash : u64, exponent, index : u32 ) -> (candidate_index : i32) | ||||
| { | ||||
| 	mask           := u32(1 << (exponent)) - 1 | ||||
| 	step           := u32(hash >> (64 - exponent)) | 1 | ||||
| 	candidate_index = i32( (index + step) & mask ) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| HMap_MSI :: struct ( $ Type : typeid, $ Size : u32 ) | ||||
| 	where is_power_of_two( Size ) | ||||
| { | ||||
| 	hashes : [ Size ]( ^ Type ), | ||||
| 	length : i32 | ||||
| } | ||||
|  | ||||
| HMap_MSI_Dyn :: struct ( $ Type : typeid ) { | ||||
| 	hashes : Array( DLL_Node( ^ Type ) ), | ||||
| 	size   : u64, | ||||
| 	length : i32, | ||||
| } | ||||
							
								
								
									
										39
									
								
								code/grime_hashmap_rjf.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								code/grime_hashmap_rjf.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| // This was an attempt to learn Ryan's hash table implementation used with the UI module of the RAD Debugger. | ||||
| // Its not completed | ||||
| package sectr | ||||
|  | ||||
| HMapRJF :: struct ( $ Type : typeid ) { | ||||
| 	slots      : Array ( DLL_NodeFL( Type ) ), | ||||
| 	size       : u64, | ||||
| 	first_free : ^ Type, | ||||
| } | ||||
|  | ||||
| rjf_hmap_init :: proc( $ Type : typeid, allocator : Allocator, size : u64 ) -> ( HMapRJF( Type ), AllocatorError ) { | ||||
| 	result      : HMapRJF( Type ) | ||||
| 	alloc_error : AllocatorError | ||||
|  | ||||
| 	result.slots, alloc_error := array_init_reserve( Type, allocator, size ) | ||||
| 	if alloc_error != AllocatorError.None { | ||||
| 		ensure( false, "Failed to allocate slots array" ) | ||||
| 		return result, alloc_error | ||||
| 	} | ||||
| 	array_resize( & result.slots, size ) | ||||
|  | ||||
| 	return result, AllocatorError.None | ||||
| } | ||||
|  | ||||
| rjf_hmap_slot_index :: #force_inline proc ( using self : HMapRJF( $ Type ), key : u64 ) -> u64 { | ||||
| 	return key % size | ||||
| } | ||||
|  | ||||
| rjf_hmap_get_slot :: #force_inline proc ( using self : HMapRJF ( $ Type ), key : u64 ) -> ^ DLL_NodeFL ( Type ) { | ||||
| 	slot_index := key % size | ||||
| 	return & slots[ slot_index ] | ||||
| } | ||||
|  | ||||
| rjf_hmap_insert :: proc ( using self : HMapRJF ( $ Type ), key : u64, value : ^ Type ) { | ||||
| 	slot_index := key % size | ||||
| 	slot := & slots[ slot_index ] | ||||
|  | ||||
| 	dll_insert_raw( nil, slot.first, slot.last, slot.last, value ) | ||||
| } | ||||
| @@ -17,6 +17,7 @@ HMapZPL_MapProc    :: #type proc( $ Type : typeid, key : u64, value :   Type ) | ||||
| HMapZPL_MapMutProc :: #type proc( $ Type : typeid, key : u64, value : ^ Type ) | ||||
| 
 | ||||
| HMapZPL_CritialLoadScale :: 0.70 | ||||
| HMapZPL_HashToEntryRatio :: 1.50 | ||||
| 
 | ||||
| HMapZPL_FindResult :: struct { | ||||
| 	hash_index  : i64, | ||||
| @@ -44,12 +45,14 @@ zpl_hmap_init_reserve :: proc( $ Type : typeid, allocator : Allocator, num : u64 | ||||
| 	result                        : HMapZPL(Type) | ||||
| 	hashes_result, entries_result : AllocatorError | ||||
| 
 | ||||
| 	result.hashes, hashes_result = array_init_reserve( i64, allocator, num ) | ||||
| 	hashes_size := cast(u64) (HMapZPL_HashToEntryRatio * f32(num)) | ||||
| 
 | ||||
| 	result.hashes, hashes_result = array_init_reserve( i64, allocator, hashes_size ) | ||||
| 	if hashes_result != AllocatorError.None { | ||||
| 		ensure( false, "Failed to allocate hashes array" ) | ||||
| 		return result, hashes_result | ||||
| 	} | ||||
| 	array_resize( & result.hashes, num ) | ||||
| 	array_resize( & result.hashes, hashes_size ) | ||||
| 	slice.fill( slice_ptr( result.hashes.data, cast(int) result.hashes.num), -1 ) | ||||
| 
 | ||||
| 	result.entries, entries_result = array_init_reserve( HMapZPL_Entry(Type), allocator, num ) | ||||
							
								
								
									
										71
									
								
								code/grime_linked_list.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								code/grime_linked_list.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| // I'm not sure about this, it was created to figure out Ryan's linked-list usage in the UI module of the RAD Debugger. | ||||
| // The code takes advantage of macros for the linked list interface in a way that odin doesn't really permit without a much worse interface. | ||||
| package sectr | ||||
|  | ||||
| DLL_Node :: struct ( $ Type : typeid ) #raw_union { | ||||
| 	using _ : struct { | ||||
| 		left, right : ^ Type, | ||||
| 	}, | ||||
| 	using _ : struct { | ||||
| 		prev, next : ^ Type, | ||||
| 	}, | ||||
| 	using _ : struct { | ||||
| 		first, last : ^ Type, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| DLL_NodeFull :: struct ( $ Type : typeid ) { | ||||
| 	first, last, prev, next : ^ Type, | ||||
| } | ||||
|  | ||||
| DLL_NodeLR :: struct ( $ Type : typeid ) { | ||||
| 	left, right : ^ Type, | ||||
| } | ||||
|  | ||||
| DLL_NodePN :: struct ( $ Type : typeid ) { | ||||
| 	prev, next : ^ Type, | ||||
| } | ||||
|  | ||||
| DLL_NodeFL :: struct ( $ Type : typeid ) { | ||||
| 	first, last : ^ Type, | ||||
| } | ||||
|  | ||||
| type_is_node :: #force_inline proc  "contextless" ( $ Type : typeid ) -> b32 | ||||
| { | ||||
| 	// elem_type := type_elem_type(Type) | ||||
| 	return type_has_field( type_elem_type(Type), "prev" ) && type_has_field( type_elem_type(Type), "next" ) | ||||
| } | ||||
|  | ||||
| dll_insert_raw ::  proc "contextless" ( null, first, last, position, new : ^ DLL_Node( $ Type ) ) | ||||
| { | ||||
| 	// Empty Case | ||||
| 	if first == null { | ||||
| 		first     = new | ||||
| 		last      = new | ||||
| 		new.next  = null | ||||
| 		new.prev  = null | ||||
| 	} | ||||
| 	else if position == null { | ||||
| 		// Position is not set, insert at beginning | ||||
| 		new.next   = first | ||||
| 		first.prev = new | ||||
| 		first      = new | ||||
| 		new.prev   = null | ||||
| 	} | ||||
| 	else if position == last { | ||||
| 		// Positin is set to last, insert at end | ||||
| 		last.next = new | ||||
| 		new.prev  = last | ||||
| 		last      = new | ||||
| 		new.next  = null | ||||
| 	} | ||||
| 	else { | ||||
| 		// Insert around position | ||||
| 		if position.next != null { | ||||
| 			position.next.prev = new | ||||
| 		} | ||||
| 		new.next      = position.next | ||||
| 		position.next = new | ||||
| 		new.prev      = position | ||||
| 	} | ||||
| } | ||||
| @@ -7,6 +7,19 @@ import "core:mem/virtual" | ||||
| import "core:runtime" | ||||
| import "core:os" | ||||
|  | ||||
| kilobytes :: #force_inline proc "contextless" ( kb : $ integer_type ) -> integer_type { | ||||
| 	return kb * Kilobyte | ||||
| } | ||||
| megabytes :: #force_inline proc "contextless" ( mb : $ integer_type ) -> integer_type { | ||||
| 	return mb * Megabyte | ||||
| } | ||||
| gigabytes  :: #force_inline proc "contextless" ( gb : $ integer_type ) -> integer_type { | ||||
| 	return gb * Gigabyte | ||||
| } | ||||
| terabytes  :: #force_inline proc "contextless" ( tb : $ integer_type ) -> integer_type { | ||||
| 	return tb * Terabyte | ||||
| } | ||||
|  | ||||
| // Initialize a sub-section of our virtual memory as a sub-arena | ||||
| sub_arena_init :: proc( address : ^ byte, size : int ) -> ( ^ Arena) { | ||||
| 	Arena :: mem.Arena | ||||
|   | ||||
| @@ -1,5 +1,10 @@ | ||||
| package sectr | ||||
|  | ||||
| is_power_of_two_u32 :: proc( value : u32 ) -> b32 | ||||
| { | ||||
| 	return value != 0 && ( value & ( value - 1 )) == 0 | ||||
| } | ||||
|  | ||||
| import "core:math/linalg" | ||||
|  | ||||
| Vec2 :: linalg.Vector2f32 | ||||
| @@ -7,31 +12,3 @@ Vec3 :: linalg.Vector3f32 | ||||
|  | ||||
| Vec2i :: [2]i32 | ||||
| Vec3i :: [3]i32 | ||||
|  | ||||
| when false { | ||||
| // TODO(Ed) : Evaluate if this is needed | ||||
|  | ||||
| Vec2 :: Vec2_f32 | ||||
| Vec2_f32 :: struct #raw_union { | ||||
| 	basis : [2] f32, | ||||
| 	using components : struct { | ||||
| 		x, y : f32 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // make_vec2 :: proc( x, y : f32 ) { | ||||
|  | ||||
| // } | ||||
|  | ||||
| Vec3 :: Vec3_f32 | ||||
| Vec3_f32 :: struct #raw_union { | ||||
| 	basis : [3] f32, | ||||
| 	using components : struct { | ||||
| 		x, y, z : f32 | ||||
| 	} | ||||
| } | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -187,7 +187,8 @@ UI_Box :: struct { | ||||
| 	label : string, | ||||
|  | ||||
| 	// Regenerated per frame. | ||||
| 	first, last, prev, next, parent : ^ UI_Box, | ||||
| 	using _      : DLL_NodeFull( UI_Box ), // first, last, prev, next | ||||
| 	parent       : ^ UI_Box, | ||||
| 	num_children : i32, | ||||
|  | ||||
| 	flags    : UI_BoxFlags, | ||||
| @@ -195,8 +196,9 @@ UI_Box :: struct { | ||||
| 	style    : UI_Style, | ||||
|  | ||||
| 	// Persistent Data | ||||
| 	// hash_links : DLL_Node_PN( ^ UI_Box), // This isn't necessary if not using RJF hash table. | ||||
| 	// prev_computed : UI_Computed, | ||||
| 	// prev_style    : UI_Style, | ||||
| 	// prev_style    : UI_Style,v | ||||
| 	mouse         : UI_InteractState, | ||||
| 	keyboard      : UI_InteractState, | ||||
| } | ||||
| @@ -240,7 +242,6 @@ UI_State :: struct { | ||||
| 	drag_start_mouse : Vec2, | ||||
| 	// drag_state_arena : ^ Arena, | ||||
| 	// drag_state data  : string, | ||||
|  | ||||
| } | ||||
|  | ||||
| ui_key_from_string :: proc( value : string ) -> UI_Key { | ||||
|   | ||||
| @@ -1,5 +0,0 @@ | ||||
| package sectr | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										43
									
								
								code/ui_rjf.odin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								code/ui_rjf.odin
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| package sectr | ||||
|  | ||||
| when false { | ||||
| 	ui_box_cache_insert :: proc( using cache : HMap_RJF( ^ UI_Box ), key : u64, value : ^ UI_Box ) -> ^ UI_Box { | ||||
| 		slot := rjf_hmap_get_slot( cache, key ) | ||||
|  | ||||
| 		// dll_insert_raw( nil, slot.first, slot.last, slot.last, value ) | ||||
| 		{ | ||||
| 			new_links := & new.hash_links | ||||
|  | ||||
| 			// Empty Case | ||||
| 			if first == null { | ||||
| 				first = new | ||||
| 				last  = new | ||||
| 				new_links.next = null | ||||
| 				new_links.prev = null | ||||
| 			} | ||||
| 			else if position == null { | ||||
| 				// Position is not set, insert at beginning | ||||
| 				new_links.next = first | ||||
| 				first.first    = new | ||||
| 				first          = new | ||||
| 				new_links.prev = null | ||||
| 			} | ||||
| 			else if position == last { | ||||
| 				// Positin is set to last, insert at end | ||||
| 				last.last      = new | ||||
| 				new_links.prev = last | ||||
| 				last           = new | ||||
| 				new_links.next = null | ||||
| 			} | ||||
| 			else { | ||||
| 				// Insert around position | ||||
| 				if position.next != null { | ||||
| 					position.next.prev = new | ||||
| 				} | ||||
| 				new.next      = position.next | ||||
| 				position.next = new | ||||
| 				new.prev      = position | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user