From 20ff4acecc3e3e00ac01179f19576418b3f809f2 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 1 Feb 2024 17:05:08 -0800 Subject: [PATCH] simplify/collapse/deduplicate eval viz block building code; correctly build filtered-info-table-sorted expansions for filtered debug info table watches; eliminate special-case empty row in watch views, just feed everything through the viz blocks path --- src/base/base_string.c | 2 - src/df/core/df_core.c | 427 ++++++++++++++++++-------------- src/df/core/df_core.h | 54 +++- src/df/gfx/df_gfx.c | 19 +- src/df/gfx/df_view_rule_hooks.c | 95 +++---- src/df/gfx/df_views.c | 377 ++++++++++++++-------------- src/df/gfx/df_views.h | 2 +- 7 files changed, 519 insertions(+), 457 deletions(-) diff --git a/src/base/base_string.c b/src/base/base_string.c index fb193622..44a90279 100644 --- a/src/base/base_string.c +++ b/src/base/base_string.c @@ -406,13 +406,11 @@ push_str8_cat(Arena *arena, String8 s1, String8 s2){ internal String8 push_str8_copy(Arena *arena, String8 s){ - //ProfBeginFunction(); String8 str; str.size = s.size; str.str = push_array_no_zero(arena, U8, str.size + 1); MemoryCopy(str.str, s.str, s.size); str.str[str.size] = 0; - //ProfEnd(); return(str); } diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index 58860c72..16125809 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -204,7 +204,6 @@ df_state_delta_history_wind(DF_StateDeltaHistory *hist, Side side) //- rjf: keys internal DF_ExpandKey - df_expand_key_make(U64 parent_hash, U64 child_num) { DF_ExpandKey key; @@ -5000,7 +4999,46 @@ df_eval_link_base_array_from_chunk_list(Arena *arena, DF_EvalLinkBaseChunkList * return array; } -//- rjf: watch tree visualization +//- rjf: viz block collection building + +internal DF_EvalVizBlock * +df_eval_viz_block_begin(Arena *arena, DF_EvalVizBlockKind kind, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth) +{ + DF_EvalVizBlockNode *n = push_array(arena, DF_EvalVizBlockNode, 1); + n->v.kind = kind; + n->v.parent_key = parent_key; + n->v.key = key; + n->v.depth = depth; + return &n->v; +} + +internal DF_EvalVizBlock * +df_eval_viz_block_split_and_continue(Arena *arena, DF_EvalVizBlockList *list, DF_EvalVizBlock *split_block, U64 split_idx) +{ + U64 total_count = split_block->semantic_idx_range.max; + split_block->visual_idx_range.max = split_block->semantic_idx_range.max = split_idx; + df_eval_viz_block_end(list, split_block); + DF_EvalVizBlock *continue_block = df_eval_viz_block_begin(arena, split_block->kind, split_block->parent_key, split_block->key, split_block->depth); + continue_block->eval = split_block->eval; + continue_block->string = split_block->string; + continue_block->member = split_block->member; + continue_block->visual_idx_range = continue_block->semantic_idx_range = r1u64(split_idx+1, total_count); + continue_block->backing_search_items = split_block->backing_search_items; + continue_block->cfg_table = split_block->cfg_table; + continue_block->link_member_type_key = split_block->link_member_type_key; + continue_block->link_member_off = split_block->link_member_off; + return continue_block; +} + +internal void +df_eval_viz_block_end(DF_EvalVizBlockList *list, DF_EvalVizBlock *block) +{ + DF_EvalVizBlockNode *n = CastFromMember(DF_EvalVizBlockNode, v, block); + SLLQueuePush(list->first, list->last, n); + list->count += 1; + list->total_visual_row_count += dim_1u64(block->visual_idx_range); + list->total_semantic_row_count += dim_1u64(block->semantic_idx_range); +} internal void df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalView *eval_view, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, DF_Eval eval, TG_Member *opt_member, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out) @@ -5029,25 +5067,18 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie ////////////////////////////// //- rjf: make and push block for root // - DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1); { - block->kind = DF_EvalVizBlockKind_Root; + DF_EvalVizBlock *block = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Root, parent_key, key, depth); block->eval = eval; block->cfg_table = *cfg_table; block->string = push_str8_copy(arena, string); - block->parent_key = parent_key; - block->key = key; block->visual_idx_range = r1u64(key.child_num-1, key.child_num+0); block->semantic_idx_range = r1u64(key.child_num-1, key.child_num+0); - block->depth = depth; if(opt_member != 0) { block->member = tg_member_copy(arena, opt_member); } - SLLQueuePush(list_out->first, list_out->last, block); - list_out->count += 1; - list_out->total_visual_row_count += 1; - list_out->total_semantic_row_count += 1; + df_eval_viz_block_end(list_out, block); } ////////////////////////////// @@ -5063,7 +5094,7 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie { TG_Key direct_type_key = tg_ptee_from_graph_raddbg_key(parse_ctx->type_graph, parse_ctx->rdbg, eval_type_key); TG_Kind direct_type_kind = tg_kind_from_key(direct_type_key); - DF_Eval ptr_val_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, block->eval); + DF_Eval ptr_val_eval = df_value_mode_eval_from_eval(parse_ctx->type_graph, parse_ctx->rdbg, ctrl_ctx, eval); // rjf: ptrs to udts if(parent_is_expanded && @@ -5175,30 +5206,20 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie udt_type_kind == TG_Kind_Class)) ProfScope("build viz blocks for UDT members") { - // rjf: get members + //- rjf: type -> filtered data members TG_MemberArray data_members = tg_data_members_from_graph_raddbg_key(scratch.arena, parse_ctx->type_graph, parse_ctx->rdbg, udt_eval.type_key); TG_MemberArray filtered_data_members = df_filtered_data_members_from_members_cfg_table(scratch.arena, data_members, cfg_table); - // rjf: make block for all members (assume no members are expanded) - DF_EvalVizBlock *memblock = push_array(arena, DF_EvalVizBlock, 1); + //- rjf: build blocks for all members, split by sub-expansions + DF_EvalVizBlock *last_vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Members, key, df_expand_key_make(df_hash_from_expand_key(key), 0), depth+1); { - memblock->kind = DF_EvalVizBlockKind_Members; - memblock->eval = udt_eval; - memblock->cfg_table = *cfg_table; - memblock->parent_key = key; - memblock->key = df_expand_key_make(df_hash_from_expand_key(key), 0); - memblock->visual_idx_range = r1u64(0, filtered_data_members.count); - memblock->semantic_idx_range = r1u64(0, filtered_data_members.count); - memblock->depth = depth+1; - SLLQueuePush(list_out->first, list_out->last, memblock); - list_out->count += 1; - list_out->total_visual_row_count += filtered_data_members.count; - list_out->total_semantic_row_count += filtered_data_members.count; + last_vb->eval = udt_eval; + last_vb->cfg_table = *cfg_table; + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, filtered_data_members.count); } - - // rjf: split memblock by sub-expansions for(DF_ExpandNode *child = node->first; child != 0; child = child->next) { + // rjf: unpack expansion info; skip out-of-bounds splits U64 child_num = child->key.child_num; U64 child_idx = child_num-1; if(child_idx >= filtered_data_members.count) @@ -5206,23 +5227,20 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie continue; } - // rjf: truncate existing memblock - memblock->visual_idx_range.max = child_idx; - memblock->semantic_idx_range.max = child_idx; + // rjf: form split: truncate & complete last block; begin next block + last_vb = df_eval_viz_block_split_and_continue(arena, list_out, last_vb, child_idx); - // rjf: build inheriting cfg table - DF_CfgTable child_cfg = *cfg_table; + // rjf: recurse for sub-expansion { - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(key), child_num)); - child_cfg = df_cfg_table_from_inheritance(arena, cfg_table); - if(view_rule_string.size != 0) + DF_CfgTable child_cfg = *cfg_table; { - df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(key), child_num)); + child_cfg = df_cfg_table_from_inheritance(arena, cfg_table); + if(view_rule_string.size != 0) + { + df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + } } - } - - // rjf: recurse for sub-block - { TG_Member *member = &filtered_data_members.v[child_idx]; DF_Eval child_eval = zero_struct; { @@ -5230,28 +5248,10 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie child_eval.mode = udt_eval.mode; child_eval.offset = udt_eval.offset + member->off; } - list_out->total_visual_row_count -= 1; - list_out->total_semantic_row_count -= 1; df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, key, child->key, member->name, child_eval, member, &child_cfg, depth+1, list_out); } - - // rjf: make new memblock for remainder of children (if any) - if(child_idx+1 < filtered_data_members.count) - { - DF_EvalVizBlock *next_memblock = push_array(arena, DF_EvalVizBlock, 1); - next_memblock->kind = DF_EvalVizBlockKind_Members; - next_memblock->eval = udt_eval; - next_memblock->cfg_table = *cfg_table; - next_memblock->parent_key = key; - next_memblock->key = df_expand_key_make(df_hash_from_expand_key(key), 0); - next_memblock->visual_idx_range = r1u64(child_idx+1, filtered_data_members.count); - next_memblock->semantic_idx_range= r1u64(child_idx+1, filtered_data_members.count); - next_memblock->depth = depth+1; - SLLQueuePush(list_out->first, list_out->last, next_memblock); - list_out->count += 1; - memblock = next_memblock; - } } + df_eval_viz_block_end(list_out, last_vb); } ////////////////////////////// @@ -5263,11 +5263,10 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie udt_type_kind == TG_Kind_Class)) ProfScope("(structs, unions, classes) descend to members & make block(s), with linked list view") { - // rjf: get members + //- rjf: type -> data members TG_MemberArray data_members = tg_data_members_from_graph_raddbg_key(scratch.arena, parse_ctx->type_graph, parse_ctx->rdbg, udt_eval.type_key); - TG_MemberArray filtered_data_members = df_filtered_data_members_from_members_cfg_table(scratch.arena, data_members, cfg_table); - // rjf: find link member + //- rjf: find link member TG_Member *link_member = 0; TG_Kind link_member_type_kind = TG_Kind_Null; TG_Key link_member_ptee_type_key = zero_struct; @@ -5283,96 +5282,73 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie } } - // rjf: invalid link member -> early-out! + //- rjf: check if link member is good + B32 link_member_is_good = 1; if(link_member == 0 || link_member_type_kind != TG_Kind_Ptr || !tg_key_match(link_member_ptee_type_key, udt_eval.type_key)) { - goto end_linked_struct_expansion_build; + link_member_is_good = 0; } - // rjf: gather link bases - DF_EvalLinkBaseChunkList link_bases = df_eval_link_base_chunk_list_from_eval(scratch.arena, parse_ctx->type_graph, parse_ctx->rdbg, link_member->type_key, link_member->off, ctrl_ctx, udt_eval, 512); - - // rjf: make block for all links (assume no members are expanded) - DF_EvalVizBlock *linkblock = push_array(arena, DF_EvalVizBlock, 1); + //- rjf: gather link bases + DF_EvalLinkBaseChunkList link_bases = {0}; + if(link_member_is_good) { - linkblock->kind = DF_EvalVizBlockKind_Links; - linkblock->eval = udt_eval; - linkblock->link_member_type_key = link_member->type_key; - linkblock->link_member_off = link_member->off; - linkblock->cfg_table = *cfg_table; - linkblock->parent_key = key; - linkblock->key = df_expand_key_make(df_hash_from_expand_key(key), 0); - linkblock->visual_idx_range = r1u64(0, link_bases.count); - linkblock->semantic_idx_range = r1u64(0, link_bases.count); - linkblock->depth = depth+1; - SLLQueuePush(list_out->first, list_out->last, linkblock); - list_out->count += 1; - list_out->total_visual_row_count += link_bases.count; - list_out->total_semantic_row_count += link_bases.count; + link_bases = df_eval_link_base_chunk_list_from_eval(scratch.arena, parse_ctx->type_graph, parse_ctx->rdbg, link_member->type_key, link_member->off, ctrl_ctx, udt_eval, 512); } - // rjf: split linkblock by sub-expansions - for(DF_ExpandNode *child = node->first; child != 0; child = child->next) + //- rjf: build blocks for all links, split by sub-expansions + if(link_member_is_good) { - U64 child_num = child->key.child_num; - U64 child_idx = child_num-1; - if(child_idx >= link_bases.count) + DF_EvalVizBlock *last_vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Links, key, df_expand_key_make(df_hash_from_expand_key(key), 0), depth+1); { - continue; + last_vb->eval = udt_eval; + last_vb->cfg_table = *cfg_table; + last_vb->link_member_type_key = link_member->type_key; + last_vb->link_member_off = link_member->off; + last_vb->visual_idx_range = r1u64(0, link_bases.count); + last_vb->semantic_idx_range = r1u64(0, link_bases.count); } - - // rjf: truncate existing elemblock - linkblock->visual_idx_range.max = child_idx; - linkblock->semantic_idx_range.max = child_idx; - - // rjf: build inheriting cfg table - DF_CfgTable child_cfg = *cfg_table; + for(DF_ExpandNode *child = node->first; child != 0; child = child->next) { - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(key), child_num)); - child_cfg = df_cfg_table_from_inheritance(arena, cfg_table); - if(view_rule_string.size != 0) + // rjf: unpack expansion info; skip out-of-bounds splits + U64 child_num = child->key.child_num; + U64 child_idx = child_num-1; + if(child_idx >= link_bases.count) { - df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + continue; + } + + // rjf: form split: truncate & complete last block; begin next block + last_vb = df_eval_viz_block_split_and_continue(arena, list_out, last_vb, child_idx); + + // rjf: find mode/offset of this link + DF_EvalLinkBase link_base = df_eval_link_base_from_chunk_list_index(&link_bases, child_idx); + + // rjf: recurse for sub-expansion + { + DF_CfgTable child_cfg = *cfg_table; + { + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(key), child_num)); + child_cfg = df_cfg_table_from_inheritance(arena, cfg_table); + if(view_rule_string.size != 0) + { + df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + } + } + DF_Eval child_eval = zero_struct; + { + child_eval.type_key = udt_eval.type_key; + child_eval.mode = link_base.mode; + child_eval.offset = link_base.offset; + } + df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, key, child->key, push_str8f(arena, "[%I64u]", child_idx), child_eval, 0, &child_cfg, depth+1, list_out); } } - - // rjf: find mode/offset of this link - DF_EvalLinkBase link_base = df_eval_link_base_from_chunk_list_index(&link_bases, child_idx); - - // rjf: recurse for sub-block - DF_Eval child_eval = zero_struct; - { - child_eval.type_key = udt_eval.type_key; - child_eval.mode = link_base.mode; - child_eval.offset = link_base.offset; - } - list_out->total_visual_row_count -= 1; - list_out->total_semantic_row_count -= 1; - df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, key, child->key, push_str8f(arena, "[%I64u]", child_idx), child_eval, 0, &child_cfg, depth+1, list_out); - - // rjf: make new elemblock for remainder of children (if any) - if(child_idx+1 < link_bases.count) - { - DF_EvalVizBlock *next_linkblock = push_array(arena, DF_EvalVizBlock, 1); - next_linkblock->kind = DF_EvalVizBlockKind_Links; - next_linkblock->eval = udt_eval; - next_linkblock->link_member_type_key = link_member->type_key; - next_linkblock->link_member_off = link_member->off; - next_linkblock->cfg_table = *cfg_table; - next_linkblock->parent_key = key; - next_linkblock->key = df_expand_key_make(df_hash_from_expand_key(key), 0); - next_linkblock->visual_idx_range = r1u64(child_idx+1, link_bases.count); - next_linkblock->semantic_idx_range = r1u64(child_idx+1, link_bases.count); - next_linkblock->depth = depth+1; - SLLQueuePush(list_out->first, list_out->last, next_linkblock); - list_out->count += 1; - linkblock = next_linkblock; - } + df_eval_viz_block_end(list_out, last_vb); } } - end_linked_struct_expansion_build:; ////////////////////////////// //- rjf: (arrays) descend to elements & make block(s), normally @@ -5381,31 +5357,22 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie arr_type_kind == TG_Kind_Array) ProfScope("(arrays) descend to elements & make block(s)") { + //- rjf: unpack array type info TG_Type *array_type = tg_type_from_graph_raddbg_key(scratch.arena, parse_ctx->type_graph, parse_ctx->rdbg, arr_eval.type_key); U64 array_count = array_type->count; TG_Key element_type_key = array_type->direct_type_key; U64 element_type_byte_size = tg_byte_size_from_graph_raddbg_key(parse_ctx->type_graph, parse_ctx->rdbg, element_type_key); - // rjf: make block for all elements (assume no elements are expanded) - DF_EvalVizBlock *elemblock = push_array(arena, DF_EvalVizBlock, 1); + //- rjf: build blocks for all elements, split by sub-expansions + DF_EvalVizBlock *last_vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Elements, key, df_expand_key_make(df_hash_from_expand_key(key), 0), depth+1); { - elemblock->kind = DF_EvalVizBlockKind_Elements; - elemblock->eval = arr_eval; - elemblock->cfg_table = *cfg_table; - elemblock->parent_key = key; - elemblock->key = df_expand_key_make(df_hash_from_expand_key(key), 0); - elemblock->visual_idx_range = r1u64(0, array_count); - elemblock->semantic_idx_range = r1u64(0, array_count); - elemblock->depth = depth+1; - SLLQueuePush(list_out->first, list_out->last, elemblock); - list_out->count += 1; - list_out->total_visual_row_count += array_count; - list_out->total_semantic_row_count += array_count; + last_vb->eval = arr_eval; + last_vb->cfg_table = *cfg_table; + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, array_count); } - - // rjf: split elemblock by sub-expansions for(DF_ExpandNode *child = node->first; child != 0; child = child->next) { + // rjf: unpack expansion info; skip out-of-bounds splits U64 child_num = child->key.child_num; U64 child_idx = child_num-1; if(child_idx >= array_count) @@ -5413,49 +5380,30 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalVie continue; } - // rjf: truncate existing elemblock - elemblock->visual_idx_range.max = child_idx; - elemblock->semantic_idx_range.max = child_idx; + // rjf: form split: truncate & complete last block; begin next block + last_vb = df_eval_viz_block_split_and_continue(arena, list_out, last_vb, child_idx); - // rjf: build inheriting cfg table - DF_CfgTable child_cfg = *cfg_table; + // rjf: recurse for sub-expansion { - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(key), child_num)); - child_cfg = df_cfg_table_from_inheritance(arena, cfg_table); - if(view_rule_string.size != 0) + DF_CfgTable child_cfg = *cfg_table; { - df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(key), child_num)); + child_cfg = df_cfg_table_from_inheritance(arena, cfg_table); + if(view_rule_string.size != 0) + { + df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + } } - } - - // rjf: recurse for sub-block - DF_Eval child_eval = zero_struct; - { - child_eval.type_key = element_type_key; - child_eval.mode = arr_eval.mode; - child_eval.offset = arr_eval.offset + child_idx*element_type_byte_size; - } - list_out->total_visual_row_count -= 1; - list_out->total_semantic_row_count -= 1; - df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, key, child->key, push_str8f(arena, "[%I64u]", child_idx), child_eval, 0, &child_cfg, depth+1, list_out); - - // rjf: make new elemblock for remainder of children (if any) - if(child_idx+1 < array_count) - { - DF_EvalVizBlock *next_elemblock = push_array(arena, DF_EvalVizBlock, 1); - next_elemblock->kind = DF_EvalVizBlockKind_Elements; - next_elemblock->eval = arr_eval; - next_elemblock->cfg_table = *cfg_table; - next_elemblock->parent_key = key; - next_elemblock->key = df_expand_key_make(df_hash_from_expand_key(key), 0); - next_elemblock->visual_idx_range = r1u64(child_idx+1, array_count); - next_elemblock->semantic_idx_range = r1u64(child_idx+1, array_count); - next_elemblock->depth = depth+1; - SLLQueuePush(list_out->first, list_out->last, next_elemblock); - list_out->count += 1; - elemblock = next_elemblock; + DF_Eval child_eval = zero_struct; + { + child_eval.type_key = element_type_key; + child_eval.mode = arr_eval.mode; + child_eval.offset = arr_eval.offset + child_idx*element_type_byte_size; + } + df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, key, child->key, push_str8f(arena, "[%I64u]", child_idx), child_eval, 0, &child_cfg, depth+1, list_out); } } + df_eval_viz_block_end(list_out, last_vb); } ////////////////////////////// @@ -5479,7 +5427,7 @@ df_eval_viz_block_list_from_eval_view_expr_num(Arena *arena, DBGI_Scope *scope, DF_EvalVizBlockList blocks = {0}; { DF_ExpandKey start_parent_key = df_expand_key_make(5381, 0); - DF_ExpandKey start_key = df_expand_key_from_eval_view_root_expr_num(eval_view, expr, num); + DF_ExpandKey start_key = df_expand_key_make(df_hash_from_expand_key(start_parent_key), num); DF_Eval eval = df_eval_from_string(arena, scope, ctrl_ctx, parse_ctx, expr); U64 expr_comma_pos = str8_find_needle(expr, 0, str8_lit(","), 0); String8List default_view_rules = {0}; @@ -5590,6 +5538,105 @@ df_idx_off_from_viz_block_key(DF_EvalVizBlock *block, DF_ExpandKey key) return idx_off; } +internal S64 +df_row_num_from_viz_block_list_key(DF_EvalVizBlockList *blocks, DF_ExpandKey key) +{ + S64 row_num = 1; + B32 found = 0; + for(DF_EvalVizBlockNode *n = blocks->first; n != 0; n = n->next) + { + DF_EvalVizBlock *block = &n->v; + if(key.parent_hash == block->key.parent_hash) + { + B32 this_block_contains_this_key = 0; + { + if(block->backing_search_items.v != 0) + { + U64 item_num = dbgi_fuzzy_item_num_from_array_element_idx__linear_search(&block->backing_search_items, key.child_num); + this_block_contains_this_key = (item_num != 0 && contains_1u64(block->semantic_idx_range, item_num-1)); + } + else + { + this_block_contains_this_key = (block->semantic_idx_range.min+1 <= key.child_num && key.child_num < block->semantic_idx_range.max+1); + } + } + if(this_block_contains_this_key) + { + found = 1; + if(block->backing_search_items.v != 0) + { + U64 item_num = dbgi_fuzzy_item_num_from_array_element_idx__linear_search(&block->backing_search_items, key.child_num); + row_num += item_num-1-block->semantic_idx_range.min; + } + else + { + row_num += key.child_num-1-block->semantic_idx_range.min; + } + break; + } + } + if(!found) + { + row_num += (S64)dim_1u64(block->semantic_idx_range); + } + } + if(!found) + { + row_num = 0; + } + return row_num; +} + +internal DF_ExpandKey +df_key_from_viz_block_list_row_num(DF_EvalVizBlockList *blocks, S64 row_num) +{ + DF_ExpandKey key = {0}; + S64 scan_y = 1; + for(DF_EvalVizBlockNode *n = blocks->first; n != 0; n = n->next) + { + DF_EvalVizBlock *vb = &n->v; + Rng1S64 vb_row_num_range = r1s64(scan_y, scan_y + (S64)dim_1u64(vb->semantic_idx_range)); + if(contains_1s64(vb_row_num_range, row_num)) + { + key = vb->key; + if(vb->backing_search_items.v != 0) + { + U64 item_idx = (U64)((row_num - vb_row_num_range.min) + vb->semantic_idx_range.min); + if(item_idx < vb->backing_search_items.count) + { + key.child_num = vb->backing_search_items.v[item_idx].idx; + } + } + else + { + key.child_num = vb->semantic_idx_range.min + (row_num - vb_row_num_range.min) + 1; + } + break; + } + scan_y += dim_1s64(vb_row_num_range); + } + return key; +} + +internal DF_ExpandKey +df_parent_key_from_viz_block_list_row_num(DF_EvalVizBlockList *blocks, S64 row_num) +{ + DF_ExpandKey key = {0}; + S64 scan_y = 1; + for(DF_EvalVizBlockNode *n = blocks->first; n != 0; n = n->next) + { + DF_EvalVizBlock *vb = &n->v; + Rng1S64 vb_row_num_range = r1s64(scan_y, scan_y + (S64)dim_1u64(vb->semantic_idx_range)); + if(contains_1s64(vb_row_num_range, row_num)) + { + key = vb->parent_key; + break; + } + scan_y += dim_1s64(vb_row_num_range); + } + return key; +} + //////////////////////////////// //~ rjf: Main State Accessors/Mutators diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index aec80717..eabc3d61 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -693,6 +693,7 @@ struct DF_EvalLinkBaseArray typedef enum DF_EvalVizBlockKind { + DF_EvalVizBlockKind_Null, // empty DF_EvalVizBlockKind_Root, // root of tree or subtree; possibly-expandable expression. DF_EvalVizBlockKind_Members, // members of struct, class, union DF_EvalVizBlockKind_Elements, // elements of array @@ -706,27 +707,49 @@ DF_EvalVizBlockKind; typedef struct DF_EvalVizBlock DF_EvalVizBlock; struct DF_EvalVizBlock { - DF_EvalVizBlock *next; + // rjf: kind & keys DF_EvalVizBlockKind kind; - DF_Eval eval; - TG_Key link_member_type_key; - U64 link_member_off; - DF_CfgTable cfg_table; - String8 string; DF_ExpandKey parent_key; DF_ExpandKey key; + S32 depth; + + // rjf: evaluation info + DF_Eval eval; + String8 string; + TG_Member *member; + + // rjf: info about ranges that this block spans Rng1U64 visual_idx_range; Rng1U64 semantic_idx_range; DBGI_FuzzySearchItemArray backing_search_items; - TG_Member *member; - S32 depth; + + // rjf: visualization config extensions + DF_CfgTable cfg_table; + TG_Key link_member_type_key; + U64 link_member_off; +}; + +typedef struct DF_EvalVizBlockNode DF_EvalVizBlockNode; +struct DF_EvalVizBlockNode +{ + DF_EvalVizBlockNode *next; + DF_EvalVizBlock v; }; typedef struct DF_EvalVizBlockList DF_EvalVizBlockList; struct DF_EvalVizBlockList { - DF_EvalVizBlock *first; - DF_EvalVizBlock *last; + DF_EvalVizBlockNode *first; + DF_EvalVizBlockNode *last; + U64 count; + U64 total_visual_row_count; + U64 total_semantic_row_count; +}; + +typedef struct DF_EvalVizBlockArray DF_EvalVizBlockArray; +struct DF_EvalVizBlockArray +{ + DF_EvalVizBlock *v; U64 count; U64 total_visual_row_count; U64 total_semantic_row_count; @@ -1540,7 +1563,7 @@ internal void df_eval_view_set_key_rule(DF_EvalView *eval_view, DF_ExpandKey key internal String8 df_eval_view_rule_from_key(DF_EvalView *eval_view, DF_ExpandKey key); //////////////////////////////// -//~ rjf: Evaluation View Visualization & Interaction +//~ rjf: Evaluation Visualization //- rjf: evaluation value string builder helpers internal String8 df_string_from_ascii_value(Arena *arena, U8 val); @@ -1555,13 +1578,20 @@ internal DF_EvalLinkBaseChunkList df_eval_link_base_chunk_list_from_eval(Arena * internal DF_EvalLinkBase df_eval_link_base_from_chunk_list_index(DF_EvalLinkBaseChunkList *list, U64 idx); internal DF_EvalLinkBaseArray df_eval_link_base_array_from_chunk_list(Arena *arena, DF_EvalLinkBaseChunkList *chunks); -//- rjf: watch tree visualization +//- rjf: viz block collection building +internal DF_EvalVizBlock *df_eval_viz_block_begin(Arena *arena, DF_EvalVizBlockKind kind, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth); +internal DF_EvalVizBlock *df_eval_viz_block_split_and_continue(Arena *arena, DF_EvalVizBlockList *list, DF_EvalVizBlock *split_block, U64 split_idx); +internal void df_eval_viz_block_end(DF_EvalVizBlockList *list, DF_EvalVizBlock *block); internal void df_append_viz_blocks_for_parent__rec(Arena *arena, DBGI_Scope *scope, DF_EvalView *view, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, DF_Eval eval, TG_Member *opt_member, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out); internal DF_EvalVizBlockList df_eval_viz_block_list_from_eval_view_expr_num(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_EvalView *eval_view, String8 expr, U64 num); internal void df_eval_viz_block_list_concat__in_place(DF_EvalVizBlockList *dst, DF_EvalVizBlockList *to_push); + +//- rjf: viz block list <-> table coordinates internal DF_ExpandKey df_key_from_viz_block_idx_off(DF_EvalVizBlock *block, U64 idx); internal B32 df_viz_block_contains_key(DF_EvalVizBlock *block, DF_ExpandKey key); internal U64 df_idx_off_from_viz_block_key(DF_EvalVizBlock *block, DF_ExpandKey key); +internal S64 df_row_num_from_viz_block_list_key(DF_EvalVizBlockList *blocks, DF_ExpandKey key); +internal DF_ExpandKey df_key_from_viz_block_list_row_num(DF_EvalVizBlockList *blocks, S64 row_num); //////////////////////////////// //~ rjf: Main State Accessors/Mutators diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index c605e6e0..a8223f14 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -7062,8 +7062,10 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop U64 visual_idx_off = 0; U64 semantic_idx_off = 0; DF_EvalVizWindowedRowList list = {0}; - for(DF_EvalVizBlock *block = blocks->first; block != 0; block = block->next) + for(DF_EvalVizBlockNode *n = blocks->first; n != 0; n = n->next) { + DF_EvalVizBlock *block = &n->v; + ////////////////////////////// //- rjf: extract block info // @@ -7149,7 +7151,7 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop ////////////////////////////// //- rjf: sum & advance // - list.count_before_visual += num_skipped_visual; + list.count_before_visual += num_skipped_visual; if(block_num_visual_rows != 0) { list.count_before_semantic += block_num_semantic_rows * num_skipped_visual / block_num_visual_rows; @@ -7164,6 +7166,19 @@ df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DBGI_Scope *scop { default:{}break; + ////////////////////////////// + //- rjf: null -> empty row + // + case DF_EvalVizBlockKind_Null: + if(visible_idx_range.max > visible_idx_range.min) + { + DF_EvalVizRow *row = push_array(arena, DF_EvalVizRow, 1); + SLLQueuePush(list.first, list.last, row); + list.count += 1; + row->key = block->key; + row->parent_key = block->parent_key; + }break; + ////////////////////////////// //- rjf: root -> just a single row. possibly expandable. // diff --git a/src/df/gfx/df_view_rule_hooks.c b/src/df/gfx/df_view_rule_hooks.c index a378a29b..2849a678 100644 --- a/src/df/gfx/df_view_rule_hooks.c +++ b/src/df/gfx/df_view_rule_hooks.c @@ -483,19 +483,12 @@ struct DF_ViewRuleHooks_RGBAState DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(rgba) { - DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1); - block->kind = DF_EvalVizBlockKind_Canvas; - block->eval = eval; - block->cfg_table = *cfg_table; - block->parent_key = key; - block->key = df_expand_key_make(df_hash_from_expand_key(key), 1); - block->visual_idx_range = r1u64(0, 8); - block->semantic_idx_range = r1u64(0, 1); - block->depth = depth; - SLLQueuePush(out->first, out->last, block); - out->count += 1; - out->total_visual_row_count += 8; - out->total_semantic_row_count += 1; + DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth); + vb->eval = eval; + vb->cfg_table = *cfg_table; + vb->visual_idx_range = r1u64(0, 8); + vb->semantic_idx_range = r1u64(0, 1); + df_eval_viz_block_end(out, vb); } DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(rgba) @@ -656,19 +649,12 @@ struct DF_ViewRuleHooks_TextState DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(text) { - DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1); - block->kind = DF_EvalVizBlockKind_Canvas; - block->eval = eval; - block->cfg_table = *cfg_table; - block->parent_key = key; - block->key = df_expand_key_make(df_hash_from_expand_key(key), 1); - block->visual_idx_range = r1u64(0, 8); - block->semantic_idx_range = r1u64(0, 1); - block->depth = depth; - SLLQueuePush(out->first, out->last, block); - out->count += 1; - out->total_visual_row_count += 8; - out->total_semantic_row_count += 1; + DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth); + vb->eval = eval; + vb->cfg_table = *cfg_table; + vb->visual_idx_range = r1u64(0, 8); + vb->semantic_idx_range = r1u64(0, 1); + df_eval_viz_block_end(out, vb); } DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text) @@ -764,19 +750,12 @@ DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(text) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(disasm) { - DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1); - block->kind = DF_EvalVizBlockKind_Canvas; - block->eval = eval; - block->cfg_table = *cfg_table; - block->parent_key = key; - block->key = df_expand_key_make(df_hash_from_expand_key(key), 1); - block->visual_idx_range = r1u64(0, 8); - block->semantic_idx_range = r1u64(0, 1); - block->depth = depth; - SLLQueuePush(out->first, out->last, block); - out->count += 1; - out->total_visual_row_count += 8; - out->total_semantic_row_count += 1; + DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth); + vb->eval = eval; + vb->cfg_table = *cfg_table; + vb->visual_idx_range = r1u64(0, 8); + vb->semantic_idx_range = r1u64(0, 1); + df_eval_viz_block_end(out, vb); } DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(disasm) @@ -855,19 +834,12 @@ internal UI_BOX_CUSTOM_DRAW(df_view_rule_hooks__bitmap_zoom_draw) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(bitmap) { - DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1); - block->kind = DF_EvalVizBlockKind_Canvas; - block->eval = eval; - block->cfg_table = *cfg_table; - block->parent_key = key; - block->key = df_expand_key_make(df_hash_from_expand_key(key), 1); - block->visual_idx_range = r1u64(0, 8); - block->semantic_idx_range = r1u64(0, 1); - block->depth = depth; - SLLQueuePush(out->first, out->last, block); - out->count += 1; - out->total_visual_row_count += 8; - out->total_semantic_row_count += 1; + DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth); + vb->eval = eval; + vb->cfg_table = *cfg_table; + vb->visual_idx_range = r1u64(0, 8); + vb->semantic_idx_range = r1u64(0, 1); + df_eval_viz_block_end(out, vb); } DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(bitmap) @@ -1101,19 +1073,12 @@ internal UI_BOX_CUSTOM_DRAW(df_view_rule_hooks__geo_box_draw) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(geo) { - DF_EvalVizBlock *block = push_array(arena, DF_EvalVizBlock, 1); - block->kind = DF_EvalVizBlockKind_Canvas; - block->eval = eval; - block->cfg_table = *cfg_table; - block->parent_key = key; - block->key = df_expand_key_make(df_hash_from_expand_key(key), 1); - block->visual_idx_range = r1u64(0, 16); - block->semantic_idx_range = r1u64(0, 1); - block->depth = depth; - SLLQueuePush(out->first, out->last, block); - out->count += 1; - out->total_visual_row_count += 16; - out->total_semantic_row_count += 1; + DF_EvalVizBlock *vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Canvas, key, df_expand_key_make(df_hash_from_expand_key(key), 1), depth); + vb->eval = eval; + vb->cfg_table = *cfg_table; + vb->visual_idx_range = r1u64(0, 16); + vb->semantic_idx_range = r1u64(0, 1); + df_eval_viz_block_end(out, vb); } DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(geo) diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index eaf940cc..4d85fea5 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -569,6 +569,7 @@ df_eval_root_alloc(DF_View *view, DF_EvalWatchViewState *ews) result->expr_buffer = push_array_no_zero(view->arena, U8, result->expr_buffer_cap); } DLLPushBack(ews->first_root, ews->last_root, result); + ews->root_count += 1; return result; } @@ -577,6 +578,7 @@ df_eval_root_release(DF_EvalWatchViewState *ews, DF_EvalRoot *root) { DLLRemove(ews->first_root, ews->last_root, root); SLLStackPush(ews->first_free_root, root); + ews->root_count -= 1; } internal void @@ -606,12 +608,13 @@ internal DF_EvalRoot * df_eval_root_from_expand_key(DF_EvalWatchViewState *ews, DF_EvalView *eval_view, DF_ExpandKey expand_key) { DF_EvalRoot *root = 0; + DF_ExpandKey parent_key = df_expand_key_make(5381, 0); + U64 parent_key_hash = df_hash_from_expand_key(parent_key); U64 num = 1; for(DF_EvalRoot *r = ews->first_root; r != 0; r = r->next, num += 1) { - String8 r_expr = df_string_from_eval_root(r); - DF_ExpandKey r_key = df_expand_key_from_eval_view_root_expr_num(eval_view, r_expr, num); - if(df_expand_key_match(r_key, expand_key)) + DF_ExpandKey key = df_expand_key_make(parent_key_hash, num); + if(df_expand_key_match(key, expand_key)) { root = r; break; @@ -627,13 +630,6 @@ df_string_from_eval_root(DF_EvalRoot *root) return string; } -internal DF_ExpandKey -df_expand_key_from_eval_view_root_expr_num(DF_EvalView *view, String8 root_expr, U64 num) -{ - DF_ExpandKey key = df_expand_key_make(df_hash_from_string(root_expr), num); - return key; -} - //- rjf: windowed watch tree visualization (both single-line and multi-line) internal DF_EvalVizBlockList @@ -725,7 +721,7 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF case DF_EvalWatchViewFillKind_ThreadLocals: case DF_EvalWatchViewFillKind_Types: { - // rjf: unpack + //- rjf: unpack context DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread); DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); U64 thread_rip_unwind_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx->unwind_count); @@ -735,7 +731,13 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, os_now_microseconds()+100); RADDBG_Parsed *rdbg = &dbgi->rdbg; - // rjf: query all filtered items from dbgi searching system + //- rjf: calculate top-level keys, expand root-level, grab root expansion node + DF_ExpandKey parent_key = df_expand_key_make(5381, 0); + DF_ExpandKey root_key = df_expand_key_make(df_hash_from_expand_key(parent_key), 0); + df_expand_set_expansion(eval_view->arena, &eval_view->expand_tree_table, df_expand_key_zero(), parent_key, 1); + DF_ExpandNode *root_node = df_expand_node_from_key(&eval_view->expand_tree_table, parent_key); + + //- rjf: query all filtered items from dbgi searching system U128 fuzzy_search_key = {(U64)view, df_hash_from_string(str8_struct(&view))}; B32 items_stale = 0; DBGI_FuzzySearchItemArray items = dbgi_fuzzy_search_items_from_key_exe_query(scope, fuzzy_search_key, exe_path, filter, DBGI_FuzzySearchTarget_UDTs, os_now_microseconds()+100, &items_stale); @@ -744,80 +746,100 @@ df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF df_gfx_request_frame(); } - // rjf: build block for all - DF_ExpandKey parent_key = df_expand_key_make(5381, 0); - DF_ExpandKey root_key = df_expand_key_make(df_hash_from_expand_key(parent_key), 0); - DF_EvalVizBlock *types_block = push_array(arena, DF_EvalVizBlock, 1); - SLLQueuePush(blocks.first, blocks.last, types_block); - types_block->kind = DF_EvalVizBlockKind_DebugInfoTable; - types_block->visual_idx_range = types_block->semantic_idx_range = r1u64(0, items.count); - types_block->parent_key = parent_key; - types_block->key = root_key; - types_block->backing_search_items = items; - blocks.count += 1; - blocks.total_visual_row_count += dim_1u64(types_block->visual_idx_range); - blocks.total_semantic_row_count += dim_1u64(types_block->semantic_idx_range); - - // rjf: split block per-expansion - df_expand_set_expansion(eval_view->arena, &eval_view->expand_tree_table, df_expand_key_zero(), parent_key, 1); - DF_ExpandNode *root_node = df_expand_node_from_key(&eval_view->expand_tree_table, parent_key); - for(DF_ExpandNode *child = root_node->first; child != 0; child = child->next) + //- rjf: gather unsorted child expansion keys + // + // Nodes are sorted in the underlying expansion tree data structure, but + // ONLY by THEIR ORDER IN THE UNDERLYING DEBUG INFO TABLE. This is + // because debug info watch rows use the DEBUG INFO TABLE INDEX to form + // their key - this provides more stable/predictable behavior as rows + // are reordered, filtered, and shuffled around, as the user filters. + // + // When we actually build viz blocks, however, we want to produce viz + // blocks BY THE ORDER OF SUB-EXPANSIONS IN THE FILTERED ITEM ARRAY + // SPACE, so that all of the expansions come out in the right order. + // + DF_ExpandKey *sub_expand_keys = 0; + U64 *sub_expand_item_idxs = 0; + U64 sub_expand_keys_count = 0; { - U64 child_num = child->key.child_num; - U64 item_num = dbgi_fuzzy_item_num_from_array_element_idx__linear_search(&items, child_num); - if(item_num == 0) + for(DF_ExpandNode *child = root_node->first; child != 0; child = child->next) { - continue; + sub_expand_keys_count += 1; } - U64 item_idx = item_num-1; - - // rjf: truncate existing memblock - types_block->visual_idx_range.max = item_idx; - types_block->semantic_idx_range.max = item_idx; - - // rjf: build inheriting cfg table - DF_CfgTable child_cfg = {0}; + sub_expand_keys = push_array(scratch.arena, DF_ExpandKey, sub_expand_keys_count); + sub_expand_item_idxs = push_array(scratch.arena, U64, sub_expand_keys_count); + U64 idx = 0; + for(DF_ExpandNode *child = root_node->first; child != 0; child = child->next) { - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(parent_key), child_num)); - if(view_rule_string.size != 0) + U64 item_num = dbgi_fuzzy_item_num_from_array_element_idx__linear_search(&items, child->key.child_num); + if(item_num != 0) { - df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + sub_expand_keys[idx] = child->key; + sub_expand_item_idxs[idx] = item_num-1; + idx += 1; + } + else + { + sub_expand_keys_count -= 1; } } + } + + //- rjf: sort child expansion keys + { + for(U64 idx1 = 0; idx1 < sub_expand_keys_count; idx1 += 1) + { + U64 min_idx2 = 0; + U64 min_item_idx = sub_expand_item_idxs[idx1]; + for(U64 idx2 = idx1+1; idx2 < sub_expand_keys_count; idx2 += 1) + { + if(sub_expand_item_idxs[idx2] < min_item_idx) + { + min_idx2 = idx2; + min_item_idx = sub_expand_item_idxs[idx2]; + } + } + if(min_idx2 != 0) + { + Swap(DF_ExpandKey, sub_expand_keys[idx1], sub_expand_keys[min_idx2]); + Swap(U64, sub_expand_item_idxs[idx1], sub_expand_item_idxs[min_idx2]); + } + } + } + + //- rjf: build blocks for all table items, split by sorted sub-expansions + DF_EvalVizBlock *last_vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_DebugInfoTable, parent_key, root_key, 0); + { + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, items.count); + last_vb->backing_search_items = items; + } + for(U64 sub_expand_idx = 0; sub_expand_idx < sub_expand_keys_count; sub_expand_idx += 1) + { + // rjf: form split: truncate & complete last block; begin next block + last_vb = df_eval_viz_block_split_and_continue(arena, &blocks, last_vb, sub_expand_item_idxs[sub_expand_idx]); - // rjf: unpack types - RADDBG_UDT *udt = raddbg_element_from_idx(parse_ctx->rdbg, udts, child_num); + // rjf: grab name for the expanded row + RADDBG_UDT *udt = raddbg_element_from_idx(parse_ctx->rdbg, udts, sub_expand_keys[sub_expand_idx].child_num); RADDBG_TypeNode *type_node = raddbg_element_from_idx(parse_ctx->rdbg, type_nodes, udt->self_type_idx); U64 name_size = 0; U8 *name_base = raddbg_string_from_idx(parse_ctx->rdbg, type_node->user_defined.name_string_idx, &name_size); String8 name = str8(name_base, name_size); - // rjf: produce eval for the expanded types - DF_Eval eval = df_eval_from_string(arena, scope, ctrl_ctx, parse_ctx, name); - - // rjf: recurse for sub-block + // rjf: recurse for sub-expansion { - blocks.total_visual_row_count -= 1; - blocks.total_semantic_row_count -= 1; - df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, parent_key, child->key, name, eval, 0, &child_cfg, 0, &blocks); - } - - // rjf: make new memblock for remainder (if any) - if(item_idx+1 < items.count) - { - DF_EvalVizBlock *next_types_block = push_array(arena, DF_EvalVizBlock, 1); - next_types_block->kind = DF_EvalVizBlockKind_DebugInfoTable; - next_types_block->visual_idx_range = r1u64(item_idx+1, items.count); - next_types_block->semantic_idx_range= r1u64(item_idx+1, items.count); - next_types_block->depth = 0; - next_types_block->parent_key = parent_key; - next_types_block->key = root_key; - next_types_block->backing_search_items = items; - SLLQueuePush(blocks.first, blocks.last, next_types_block); - blocks.count += 1; - types_block = next_types_block; + DF_CfgTable child_cfg = {0}; + { + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, df_expand_key_make(df_hash_from_expand_key(parent_key), sub_expand_keys[sub_expand_idx].child_num)); + if(view_rule_string.size != 0) + { + df_cfg_table_push_unparsed_string(arena, &child_cfg, view_rule_string, DF_CfgSrc_User); + } + } + DF_Eval eval = df_eval_from_string(arena, scope, ctrl_ctx, parse_ctx, name); + df_append_viz_blocks_for_parent__rec(arena, scope, eval_view, ctrl_ctx, parse_ctx, parent_key, sub_expand_keys[sub_expand_idx], name, eval, 0, &child_cfg, 0, &blocks); } } + df_eval_viz_block_end(&blocks, last_vb); }break; } scratch_end(scratch); @@ -903,44 +925,25 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW // DF_EvalVizBlockList blocks = df_eval_viz_block_list_from_watch_view_state(scratch.arena, scope, &ctrl_ctx, &parse_ctx, view, ewv); + ////////////////////////////// + //- rjf: does this eval watch view allow mutation? -> add extra block for editable empty row + // + DF_ExpandKey empty_row_parent_key = df_expand_key_make(max_U64, max_U64); + DF_ExpandKey empty_row_key = df_expand_key_make(df_hash_from_expand_key(empty_row_parent_key), 0); + if(modifiable) + { + DF_EvalVizBlock *b = df_eval_viz_block_begin(scratch.arena, DF_EvalVizBlockKind_Null, empty_row_parent_key, empty_row_key, 0); + b->visual_idx_range = b->semantic_idx_range = r1u64(0, 1); + df_eval_viz_block_end(&blocks, b); + } + ////////////////////////////// //- rjf: selection state * blocks -> 2D table coordinates // Vec2S64 cursor = {0}; { cursor.x = ewv->selected_column; - if(df_expand_key_match(df_expand_key_make(0, 0), ewv->selected_parent_key)) - { - cursor.y = 0; - } - else if(df_expand_key_match(df_expand_key_make(1, 1), ewv->selected_parent_key)) - { - cursor.y = blocks.total_semantic_row_count+1; - } - else - { - B32 key_found = 0; - cursor.y = 1; - for(DF_EvalVizBlock *block = blocks.first; block != 0; block = block->next) - { - if(df_expand_key_match(block->parent_key, ewv->selected_parent_key) && - block->key.parent_hash == ewv->selected_key.parent_hash && - df_viz_block_contains_key(block, ewv->selected_key)) - { - key_found = 1; - cursor.y += df_idx_off_from_viz_block_key(block, ewv->selected_key); - break; - } - else - { - cursor.y += dim_1u64(block->semantic_idx_range); - } - } - if(key_found == 0) - { - cursor.y = 1*!!modifiable; - } - } + cursor.y = df_row_num_from_viz_block_list_key(&blocks, ewv->selected_key); } ////////////////////////////// @@ -1021,20 +1024,16 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW scroll_list_params.flags = UI_ScrollListFlag_All; scroll_list_params.row_height_px = floor_f32(ui_top_font_size()*2.5f); scroll_list_params.dim_px = dim_2f32(rect); - scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, blocks.total_semantic_row_count + 1*!!modifiable)); - scroll_list_params.item_range = r1s64(0, 1 + blocks.total_visual_row_count + 1*!!modifiable); + scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(3, blocks.total_semantic_row_count)); + scroll_list_params.item_range = r1s64(0, 1 + blocks.total_visual_row_count); scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; UI_ScrollListRowBlockChunkList row_block_chunks = {0}; - for(DF_EvalVizBlock *viz_block = blocks.first; viz_block != 0; viz_block = viz_block->next) + for(DF_EvalVizBlockNode *n = blocks.first; n != 0; n = n->next) { + DF_EvalVizBlock *vb = &n->v; UI_ScrollListRowBlock block = {0}; - block.row_count = dim_1u64(viz_block->visual_idx_range); - block.item_count = dim_1u64(viz_block->semantic_idx_range); - ui_scroll_list_row_block_chunk_list_push(scratch.arena, &row_block_chunks, 256, &block); - } - if(modifiable) - { - UI_ScrollListRowBlock block = {1, 1}; + block.row_count = dim_1u64(vb->visual_idx_range); + block.item_count = dim_1u64(vb->semantic_idx_range); ui_scroll_list_row_block_chunk_list_push(scratch.arena, &row_block_chunks, 256, &block); } scroll_list_params.row_blocks = ui_scroll_list_row_block_array_from_chunk_list(scratch.arena, &row_block_chunks); @@ -1107,6 +1106,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW for(DF_EvalVizRow *row = rows.first; row != 0; row = row->next, semantic_idx += 1) { U64 row_hash = df_hash_from_expand_key(row->key); + U64 expr_hash = df_hash_from_string(row->expr); df_expand_tree_table_animate(&eval_view->expand_tree_table, df_dt()); B32 row_selected = ((semantic_idx+1) == cursor.y); B32 row_expanded = df_expand_key_is_set(&eval_view->expand_tree_table, row->key); @@ -1179,7 +1179,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW { ui_set_next_overlay_color(mul_4f32(df_rgba_from_theme_color(DF_ThemeColor_Highlight0), v4f32(1, 1, 1, 0.2f))); } - UI_NamedTableVectorF("row_%I64x", row_hash) + UI_NamedTableVectorF("row_%I64x_%I64x_%I64x", row_hash, expr_hash, ewv->root_count) { //- rjf: expression ProfScope("expr") @@ -1342,7 +1342,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW { B32 cell_selected = (row_selected && cursor.x == DF_EvalWatchViewColumnKind_Value); B32 value_is_error = (row->errors.count != 0); - B32 value_is_hook = (!value_is_error && row->value_ui_rule_spec != &df_g_nil_gfx_view_rule_spec); + B32 value_is_hook = (!value_is_error && row->value_ui_rule_spec != &df_g_nil_gfx_view_rule_spec && row->value_ui_rule_spec != 0); B32 value_is_complex = (!value_is_error && !value_is_hook && !(row->flags & DF_EvalVizRowFlag_CanEditValue)); B32 value_is_simple = (!value_is_error && !value_is_hook && (row->flags & DF_EvalVizRowFlag_CanEditValue)); @@ -1509,6 +1509,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW } //- rjf: empty row for edits +#if 0 if(visible_row_rng.max >= scroll_list_params.item_range.max-1) if(modifiable) { ui_set_next_flags(disabled_flags); @@ -1621,6 +1622,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW } } } +#endif } } @@ -1647,76 +1649,65 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW { commit_string = edit_autocomplete_string; } - - //- rjf: committed on empty row -> create new - if(commit_row == 0 && commit_string.size != 0) + switch(commit_column) { - DF_EvalRoot *root = df_eval_root_alloc(view, ewv); - df_eval_root_equip_string(root, commit_string); - U64 root_expr_hash = df_hash_from_string(commit_string); - DF_EvalViewKey root_view_key = df_eval_view_key_make((U64)root, root_expr_hash); - DF_EvalView *root_view = df_eval_view_from_key(root_view_key); - DF_ExpandKey parent_key = df_expand_key_make(5381, 0); - DF_ExpandKey key = df_expand_key_make(root_expr_hash, 1); - df_expand_set_expansion(root_view->arena, &root_view->expand_tree_table, parent_key, key, 0); - cursor.y += 1; - } - - //- rjf: committed on a valid row - if(commit_row != 0) - { - switch(commit_column) + default:break; + + //- rjf: expression commits + case DF_EvalWatchViewColumnKind_Expr: if(modifiable) { - default:break; - - //- rjf: expression commits - case DF_EvalWatchViewColumnKind_Expr: if(modifiable) + if(commit_string.size == 0) { - if(commit_string.size == 0) + DF_EvalRoot *root = df_eval_root_from_expand_key(ewv, eval_view, commit_row->key); + if(root != 0) { - DF_EvalRoot *root = df_eval_root_from_expand_key(ewv, eval_view, commit_row->key); - if(root != 0) - { - df_eval_root_release(ewv, root); - } + df_eval_root_release(ewv, root); } - else + } + else + { + DF_EvalRoot *root = df_eval_root_from_expand_key(ewv, eval_view, commit_row->key); + if(!root && df_expand_key_match(commit_row->key, empty_row_key)) { - DF_EvalRoot *root = df_eval_root_from_expand_key(ewv, eval_view, commit_row->key); - if(root != 0) - { - df_eval_root_equip_string(root, commit_string); - } + root = df_eval_root_alloc(view, ewv); } - }break; - - //- rjf: value commits - case DF_EvalWatchViewColumnKind_Value: - { - Temp scratch = scratch_begin(0, 0); - DF_Eval write_eval = df_eval_from_string(scratch.arena, scope, &ctrl_ctx, &parse_ctx, commit_string); - B32 success = df_commit_eval_value(parse_ctx.type_graph, parse_ctx.rdbg, &ctrl_ctx, commit_row->eval, write_eval); - if(success == 0) + if(root != 0) { - DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); - params.string = str8_lit("Could not commit value successfully."); - df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_String); - df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error)); + df_eval_root_equip_string(root, commit_string); } - scratch_end(scratch); - }break; - - //- rjf: type commits - case DF_EvalWatchViewColumnKind_Type: + } + }break; + + //- rjf: value commits + case DF_EvalWatchViewColumnKind_Value: + { + Temp scratch = scratch_begin(0, 0); + DF_Eval write_eval = df_eval_from_string(scratch.arena, scope, &ctrl_ctx, &parse_ctx, commit_string); + B32 success = df_commit_eval_value(parse_ctx.type_graph, parse_ctx.rdbg, &ctrl_ctx, commit_row->eval, write_eval); + if(success == 0) { - }break; - - //- rjf: view rule commits - case DF_EvalWatchViewColumnKind_ViewRule: - { - df_eval_view_set_key_rule(eval_view, commit_row->key, commit_string); - }break; - } + DF_CmdParams params = df_cmd_params_from_view(ws, panel, view); + params.string = str8_lit("Could not commit value successfully."); + df_cmd_params_mark_slot(¶ms, DF_CmdParamSlot_String); + df_push_cmd__root(¶ms, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Error)); + } + scratch_end(scratch); + }break; + + //- rjf: type commits + case DF_EvalWatchViewColumnKind_Type: + { + }break; + + //- rjf: view rule commits + case DF_EvalWatchViewColumnKind_ViewRule: + { + df_eval_view_set_key_rule(eval_view, commit_row->key, commit_string); + }break; + } + if(edit_submit && commit_string.size != 0) + { + cursor.y += 1; } } } @@ -1729,20 +1720,18 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW ewv->input_editing = 0; } - ////////////////////////////// - //- rjf: commit was submitted -> advance to next row - // - if(edit_submit) - { - cursor.y += 1; - } - ////////////////////////////// //- rjf: commits occurred -> re-compute blocks to adjust to new state // if(edit_commit) { blocks = df_eval_viz_block_list_from_watch_view_state(scratch.arena, scope, &ctrl_ctx, &parse_ctx, view, ewv); + if(modifiable) + { + DF_EvalVizBlock *b = df_eval_viz_block_begin(scratch.arena, DF_EvalVizBlockKind_Null, empty_row_parent_key, empty_row_key, 0); + b->visual_idx_range = b->semantic_idx_range = r1u64(0, 1); + df_eval_viz_block_end(&blocks, b); + } } ////////////////////////////// @@ -1752,9 +1741,20 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW DF_ExpandKey last_selected_key = ewv->selected_key; DF_ExpandKey last_selected_parent_key = ewv->selected_parent_key; ewv->selected_column = (DF_EvalWatchViewColumnKind)cursor.x; + ewv->selected_key = df_key_from_viz_block_list_row_num(&blocks, cursor.y); + ewv->selected_parent_key = df_parent_key_from_viz_block_list_row_num(&blocks, cursor.y); + if(df_expand_key_match(df_expand_key_zero(), ewv->selected_key)) + { + ewv->selected_key = last_selected_parent_key; + DF_ExpandNode *node = df_expand_node_from_key(&eval_view->expand_tree_table, last_selected_parent_key); + for(DF_ExpandNode *n = node; n != 0; n = n->parent) + { + ewv->selected_key = n->key; + } + } +#if 0 ewv->selected_parent_key = df_expand_key_make(0, 0); ewv->selected_key = df_expand_key_make(0, 0); - S64 scan_y = 1; if(cursor.y == 0) { ewv->selected_parent_key = df_expand_key_make(0, 0); @@ -1770,6 +1770,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW DF_EvalVizBlock *block_before_found = 0; DF_EvalVizBlock *found_block = 0; DF_EvalVizBlock *prev = 0; + S64 scan_y = 1; for(DF_EvalVizBlock *block = blocks.first; block != 0; prev = block, block = block->next) { S64 advance = (S64)dim_1u64(block->semantic_idx_range); @@ -1807,6 +1808,7 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW } } } +#endif if(!df_expand_key_match(ewv->selected_key, last_selected_key) || !df_expand_key_match(ewv->selected_parent_key, last_selected_parent_key)) { @@ -6677,6 +6679,8 @@ DF_VIEW_SETUP_FUNCTION_DEF(Watch) // rjf: add roots for watches { + DF_ExpandKey parent_key = df_expand_key_make(5381, 0); + U64 parent_key_hash = df_hash_from_expand_key(parent_key); DF_EvalViewKey eval_view_key = df_eval_view_key_from_eval_watch_view(ewv); DF_EvalView *eval_view = df_eval_view_from_key(eval_view_key); U64 num = 1; @@ -6688,13 +6692,14 @@ DF_VIEW_SETUP_FUNCTION_DEF(Watch) df_eval_root_equip_string(root, expr->string); if(expr->first != &df_g_nil_cfg_node) { - DF_ExpandKey root_key = df_expand_key_from_eval_view_root_expr_num(eval_view, expr->string, num); + DF_ExpandKey root_key = df_expand_key_make(parent_key_hash, num); String8 view_rule = expr->first->string; df_eval_view_set_key_rule(eval_view, root_key, view_rule); } } } } + ProfEnd(); } @@ -6706,12 +6711,14 @@ DF_VIEW_STRING_FROM_STATE_FUNCTION_DEF(Watch) DF_EvalViewKey eval_view_key = df_eval_view_key_from_eval_watch_view(ewv); DF_EvalView *eval_view = df_eval_view_from_key(eval_view_key); { + DF_ExpandKey parent_key = df_expand_key_make(5381, 0); + U64 parent_key_hash = df_hash_from_expand_key(parent_key); U64 num = 1; for(DF_EvalRoot *root = ewv->first_root; root != 0; root = root->next, num += 1) { String8 string = df_string_from_eval_root(root); str8_list_pushf(arena, &strs, "\"%S\"", string); - DF_ExpandKey root_key = df_expand_key_from_eval_view_root_expr_num(eval_view, string, num); + DF_ExpandKey root_key = df_expand_key_make(parent_key_hash, num); String8 view_rule = df_eval_view_rule_from_key(eval_view, root_key); if(view_rule.size != 0) { diff --git a/src/df/gfx/df_views.h b/src/df/gfx/df_views.h index 25645743..d55ad672 100644 --- a/src/df/gfx/df_views.h +++ b/src/df/gfx/df_views.h @@ -316,6 +316,7 @@ struct DF_EvalWatchViewState DF_EvalRoot *first_root; DF_EvalRoot *last_root; DF_EvalRoot *first_free_root; + U64 root_count; }; //////////////////////////////// @@ -444,7 +445,6 @@ internal void df_eval_root_equip_string(DF_EvalRoot *root, String8 str internal DF_EvalRoot * df_eval_root_from_string(DF_EvalWatchViewState *ews, String8 string); internal DF_EvalRoot * df_eval_root_from_expand_key(DF_EvalWatchViewState *ews, DF_EvalView *eval_view, DF_ExpandKey expand_key); internal String8 df_string_from_eval_root(DF_EvalRoot *root); -internal DF_ExpandKey df_expand_key_from_eval_view_root_expr_num(DF_EvalView *view, String8 root_expr, U64 num); //- rjf: windowed watch tree visualization internal DF_EvalVizBlockList df_eval_viz_block_list_from_watch_view_state(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_View *view, DF_EvalWatchViewState *ews);