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:
parent
1de141288f
commit
12aa6b4870
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user