diff --git a/project.4coder b/project.4coder index 767c54a9..5580d42e 100644 --- a/project.4coder +++ b/project.4coder @@ -48,7 +48,7 @@ commands = //- rjf: fkey command slots (change locally but do not commit) .f1 = { .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, .f2 = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, - .f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --auto_step && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, + .f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --auto_run && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, //- rjf: local target builds .build_raddbg = { .win = "build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, }, diff --git a/src/eval/eval_types.h b/src/eval/eval_types.h index 643dc3e2..05a1d181 100644 --- a/src/eval/eval_types.h +++ b/src/eval/eval_types.h @@ -243,6 +243,7 @@ struct E_TypeState //////////////////////////////// //~ rjf: Globals +global read_only E_Member e_member_nil = {E_MemberKind_Null, zero_struct, {0}, {0}, 0, {0}}; global read_only E_Type e_type_nil = {E_TypeKind_Null}; thread_static E_TypeState *e_type_state = 0; diff --git a/src/eval_visualization/eval_visualization_builtin_view_rules.c b/src/eval_visualization/eval_visualization_builtin_view_rules.c index 688581dd..de0a3239 100644 --- a/src/eval_visualization/eval_visualization_builtin_view_rules.c +++ b/src/eval_visualization/eval_visualization_builtin_view_rules.c @@ -103,6 +103,7 @@ EV_VIEW_RULE_EXPR_EXPAND_FUNCTION_DEF(default) { EV_ExpandResult result = {0}; Temp scratch = scratch_begin(&arena, 1); + U64 needed_row_count = dim_1u64(idx_range); //////////////////////////// //- rjf: unpack expression type info @@ -125,17 +126,16 @@ EV_VIEW_RULE_EXPR_EXPAND_FUNCTION_DEF(default) { E_MemberArray members = e_type_data_members_from_key__cached(e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key); result.total_semantic_row_count = result.total_visual_row_count = members.count; - result.row_exprs_count = dim_1u64(idx_range); + result.row_exprs_count = Min(needed_row_count, members.count); result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count); + result.row_members = push_array(arena, E_Member *, result.row_exprs_count); + result.row_exprs_num_visual_rows = push_array(arena, U64, result.row_exprs_count); for EachIndex(row_expr_idx, result.row_exprs_count) { - result.row_exprs[row_expr_idx] = &e_expr_nil; - U64 member_idx = idx_range.min + row_expr_idx; - if(member_idx < members.count) - { - E_Member *member = &members.v[member_idx]; - result.row_exprs[row_expr_idx] = e_expr_ref_member_access(arena, expr, member->name); - } + E_Member *member = &members.v[idx_range.min + row_expr_idx]; + result.row_exprs[row_expr_idx] = e_expr_ref_member_access(arena, expr, member->name); + result.row_members[row_expr_idx] = member; + result.row_exprs_num_visual_rows[row_expr_idx] = 1; } } @@ -147,17 +147,16 @@ EV_VIEW_RULE_EXPR_EXPAND_FUNCTION_DEF(default) { E_Type *type = e_type_from_key(arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key); result.total_semantic_row_count = result.total_visual_row_count = type->count; - result.row_exprs_count = dim_1u64(idx_range); + result.row_exprs_count = Min(needed_row_count, type->count); result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count); + result.row_members = push_array(arena, E_Member *, result.row_exprs_count); + result.row_exprs_num_visual_rows = push_array(arena, U64, result.row_exprs_count); for EachIndex(row_expr_idx, result.row_exprs_count) { - result.row_exprs[row_expr_idx] = &e_expr_nil; - U64 enumval_idx = idx_range.min + row_expr_idx; - if(enumval_idx < type->count) - { - E_EnumVal *enumval = &type->enum_vals[enumval_idx]; - result.row_exprs[row_expr_idx] = e_expr_ref_member_access(arena, expr, enumval->name); - } + E_EnumVal *enumval = &type->enum_vals[idx_range.min + row_expr_idx]; + result.row_exprs[row_expr_idx] = e_expr_ref_member_access(arena, expr, enumval->name); + result.row_members[row_expr_idx] = &e_member_nil; + result.row_exprs_num_visual_rows[row_expr_idx] = 1; } } @@ -171,16 +170,15 @@ EV_VIEW_RULE_EXPR_EXPAND_FUNCTION_DEF(default) E_Expr *array_expr = need_extra_deref ? e_expr_ref_deref(arena, expr) : expr; E_Type *type = e_type_from_key(arena, need_extra_deref ? direct_type_key : type_key); result.total_semantic_row_count = result.total_visual_row_count = type->count; - result.row_exprs_count = dim_1u64(idx_range); + result.row_exprs_count = Min(needed_row_count, type->count); result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count); + result.row_members = push_array(arena, E_Member *, result.row_exprs_count); + result.row_exprs_num_visual_rows = push_array(arena, U64, result.row_exprs_count); for EachIndex(row_expr_idx, result.row_exprs_count) { - result.row_exprs[row_expr_idx] = &e_expr_nil; - U64 element_idx = idx_range.min + row_expr_idx; - if(element_idx < type->count) - { - result.row_exprs[row_expr_idx] = e_expr_ref_array_index(arena, array_expr, element_idx); - } + result.row_exprs[row_expr_idx] = e_expr_ref_array_index(arena, array_expr, idx_range.min + row_expr_idx); + result.row_members[row_expr_idx] = &e_member_nil; + result.row_exprs_num_visual_rows[row_expr_idx] = 1; } } @@ -189,17 +187,13 @@ EV_VIEW_RULE_EXPR_EXPAND_FUNCTION_DEF(default) // else if(e_type_kind_is_pointer_or_ref(type_kind) && e_type_kind_is_pointer_or_ref(direct_type_kind)) { - result.total_semantic_row_count = result.total_visual_row_count = 1; - result.row_exprs_count = dim_1u64(idx_range); + result.total_semantic_row_count = result.total_visual_row_count = result.row_exprs_count = 1; result.row_exprs = push_array(arena, E_Expr *, result.row_exprs_count); - for EachIndex(row_expr_idx, result.row_exprs_count) - { - result.row_exprs[row_expr_idx] = &e_expr_nil; - if(idx_range.min + row_expr_idx < 1) - { - result.row_exprs[row_expr_idx] = e_expr_ref_deref(arena, expr); - } - } + result.row_members = push_array(arena, E_Member *, result.row_exprs_count); + result.row_exprs_num_visual_rows = push_array(arena, U64, result.row_exprs_count); + result.row_exprs[0] = e_expr_ref_deref(arena, expr); + result.row_members[0] = &e_member_nil; + result.row_exprs_num_visual_rows[0] = 1; } scratch_end(scratch); diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index 02ff58ba..1920404b 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -491,6 +491,195 @@ ev_expr_from_expr_view_rules(Arena *arena, E_Expr *expr, EV_ViewRuleList *view_r return expr; } +//////////////////////////////// +//~ rjf: Block Building (v2) + +internal EV2_BlockTree +ev2_block_tree_from_expr(Arena *arena, EV_View *view, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules) +{ + EV2_BlockTree tree = {&ev2_nil_block}; + { + Temp scratch = scratch_begin(&arena, 1); + EV_ViewRuleInfo *default_expand_view_rule_info = ev_view_rule_info_from_string(str8_lit("default")); + + //- rjf: generate root block + tree.root = push_array(arena, EV2_Block, 1); + MemoryCopyStruct(tree.root, &ev2_nil_block); + tree.root->key = ev_key_make(5381, 1); + tree.root->string = string; + tree.root->expr = expr; + tree.root->view_rules = view_rules; + tree.root->semantic_row_count = tree.root->visual_row_count = 1; + + //- rjf: iterate all expansions & generate blocks for each + typedef struct Task Task; + struct Task + { + Task *next; + EV2_Block *parent_block; + U64 split_relative_idx; + }; + Task start_task = {0, tree.root, 1}; + Task *first_task = &start_task; + Task *last_task = first_task; + for(Task *t = first_task; t != 0; t = t->next) + { + EV_ExpandNode *expand_node = ev_expand_node_from_key(view, t->parent_block->key); + + // rjf: skip if not expanded + if(!expand_node || !expand_node->expanded) + { + continue; + } + + // rjf: get expansion view rule info + EV_ViewRuleInfo *expand_view_rule_info = &ev_nil_view_rule_info; + MD_Node *expand_params = &md_nil_node; + for(EV_ViewRuleNode *n = t->parent_block->view_rules->first; n != 0; n = n->next) + { + EV_ViewRuleInfo *info = ev_view_rule_info_from_string(n->v.root->string); + if(info->expr_expand != 0) + { + expand_view_rule_info = info; + expand_params = n->v.root; + } + } + + // rjf: get expansion info + EV_ExpandResult expand_result = expand_view_rule_info->expr_expand(arena, t->parent_block->expr, expand_params, r1u64(0, 0)); + + // rjf: generate block for expansion + EV2_Block *expansion_block = push_array(arena, EV2_Block, 1); + MemoryCopyStruct(expansion_block, &ev2_nil_block); + DLLPushBack(t->parent_block->first, t->parent_block->last, expansion_block); + expansion_block->parent = t->parent_block; + expansion_block->key = t->parent_block->key; + expansion_block->split_relative_idx = t->split_relative_idx; + expansion_block->expr = t->parent_block->expr; + expansion_block->view_rules = t->parent_block->view_rules; + expansion_block->expand_view_rule_info = expand_view_rule_info; + expansion_block->expand_view_rule_params = expand_params; + expansion_block->semantic_row_count = expand_result.total_semantic_row_count; + expansion_block->visual_row_count = expand_result.total_visual_row_count; + tree.total_semantic_row_count += expand_result.total_semantic_row_count; + tree.total_visual_row_count += expand_result.total_visual_row_count; + + // rjf: iterate children expansions, generate children blocks for each + // TODO(rjf): need to iterate these in index order, rather than "child_num" (which needs to be renamed to "child_id") order + for(EV_ExpandNode *child = expand_node->first; child != 0; child = child->next) + { + Task *task = push_array(scratch.arena, Task, 1); + SLLQueuePush(first_task, last_task, task); + task->parent_block = expansion_block; + task->split_relative_idx = child->key.child_num - 1; // TODO(rjf): key -> index + } + } + scratch_end(scratch); + } + return tree; +} + +internal EV2_WindowedRowList +ev2_windowed_row_list_from_block_tree(Arena *arena, EV_View *view, EV2_BlockTree *block_tree, Rng1U64 visible_range) +{ + EV2_WindowedRowList rows = {0}; + { + Temp scratch = scratch_begin(&arena, 1); + typedef struct BlockTask BlockTask; + struct BlockTask + { + BlockTask *next; + EV2_Block *block; + EV2_Block *next_child; + Rng1U64 block_relative_range; + }; + U64 visual_idx_off = 0; + BlockTask start_task = {0, block_tree->root, block_tree->root->first, r1u64(0, block_tree->root->visual_row_count)}; + for(BlockTask *t = &start_task; t != 0; t = t->next) + { + // rjf: get block-relative range, truncated by split position of next child + Rng1U64 block_relative_range = t->block_relative_range; + block_relative_range.max = Min(t->next_child->split_relative_idx, block_relative_range.max); + U64 block_num_visual_rows = dim_1u64(block_relative_range); + + // rjf: get global range of this block + Rng1U64 block_global_range = r1u64(visual_idx_off, visual_idx_off + block_num_visual_rows); + + // rjf: get skip/chop of global range + U64 num_skipped = 0; + U64 num_chopped = 0; + { + if(visible_range.min > block_global_range.min) + { + num_skipped = (visible_range.min - block_global_range.min); + num_skipped = Min(num_skipped, block_num_visual_rows); + } + if(visible_range.max < block_global_range.max) + { + num_chopped = (block_global_range.max - visible_range.max); + num_chopped = Min(num_chopped, block_num_visual_rows); + } + } + + // rjf: get block-relative *windowed* range + Rng1U64 block_relative_range__windowed = r1u64(block_relative_range.min + num_skipped, + block_relative_range.max - num_chopped); + + // rjf: sum & advance + visual_idx_off += block_num_visual_rows; + + // rjf: generate rows before next splitting child + if(block_relative_range__windowed.max > block_relative_range__windowed.min) + { + EV_ExpandResult expand = t->block->expand_view_rule_info->expr_expand(arena, t->block->expr, t->block->expand_view_rule_params, block_relative_range__windowed); + for EachIndex(idx, expand.row_exprs_count) + { + U64 row_visual_size = expand.row_exprs_num_visual_rows[idx]; + U64 child_id = block_relative_range.min + idx + 1; // TODO(rjf): index -> key + EV2_Row *row = push_array(arena, EV2_Row, 1); + SLLQueuePush(rows.first, rows.last, row); + row->block = t->block; + row->key = ev_key_make(ev_hash_from_key(row->block->key), child_id); + row->visual_size = row_visual_size; + row->visual_size_skipped = 0; // TODO(rjf) + row->visual_size_chopped = 0; // TODO(rjf) + row->string = t->block->string; + row->expr = expand.row_exprs[idx]; + row->member = expand.row_members[idx]; + row->view_rules = ev_view_rule_list_from_inheritance(arena, t->block->view_rules); + // TODO(rjf): mix in view rules based on row's key, row's type + } + } + + // rjf: generate task for child, + for post-child parts of this block + if(t->next_child != &ev2_nil_block) + { + // rjf: generate task for child - do *before* remainder (descend block tree depth first) + BlockTask *child_task = push_array(scratch.arena, BlockTask, 1); + child_task->next = t->next; + t->next = child_task; + child_task->block = t->next_child; + child_task->next_child = t->next_child->first; + child_task->block_relative_range = r1u64(0, t->next_child->visual_row_count); + + // rjf: generate task for post-child rows, if any, after children + Rng1U64 remainder_range = r1u64(t->next_child->split_relative_idx, t->block_relative_range.max); + if(remainder_range.max > remainder_range.min) + { + BlockTask *remainder_task = push_array(scratch.arena, BlockTask, 1); + remainder_task->next = child_task->next; + child_task->next = remainder_task; + remainder_task->block = t->block; + remainder_task->next_child = t->next_child->next; + remainder_task->block_relative_range = remainder_range; + } + } + } + scratch_end(scratch); + } + return rows; +} + //////////////////////////////// //~ rjf: Block Building diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index 74f11484..647a7522 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -108,6 +108,8 @@ struct EV_ExpandResult U64 total_visual_row_count; U64 row_exprs_count; E_Expr **row_exprs; + E_Member **row_members; + U64 *row_exprs_num_visual_rows; }; //////////////////////////////// @@ -237,6 +239,79 @@ struct EV_ViewRuleInfoTable U64 slots_count; }; +//////////////////////////////// +//~ rjf: Blocks (v2) + +typedef struct EV2_Block EV2_Block; +struct EV2_Block +{ + // rjf: links + EV2_Block *first; + EV2_Block *last; + EV2_Block *next; + EV2_Block *prev; + EV2_Block *parent; + + // rjf: key + EV_Key key; + + // rjf: split index, relative to parent's space + U64 split_relative_idx; + + // rjf: expression / visualization info + String8 string; + E_Expr *expr; + EV_ViewRuleList *view_rules; + EV_ViewRuleInfo *expand_view_rule_info; + MD_Node *expand_view_rule_params; + + // rjf: expansion info + U64 semantic_row_count; + U64 visual_row_count; +}; + +typedef struct EV2_BlockTree EV2_BlockTree; +struct EV2_BlockTree +{ + EV2_Block *root; + U64 total_semantic_row_count; + U64 total_visual_row_count; +}; + +//////////////////////////////// +//~ rjf: Rows (v2) + +typedef struct EV2_Row EV2_Row; +struct EV2_Row +{ + EV2_Row *next; + + // rjf: block hierarchy info + EV2_Block *block; + EV_Key key; + + // rjf: row size/scroll info + U64 visual_size; + U64 visual_size_skipped; + U64 visual_size_chopped; + + // rjf: expression / visualization info + String8 string; + E_Expr *expr; + E_Member *member; + EV_ViewRuleList *view_rules; +}; + +typedef struct EV2_WindowedRowList EV2_WindowedRowList; +struct EV2_WindowedRowList +{ + EV2_Row *first; + EV2_Row *last; + U64 count; + U64 count_before_visual; + U64 count_before_semantic; +}; + //////////////////////////////// //~ rjf: Automatic Type -> View Rule Map Types @@ -320,6 +395,7 @@ global read_only EV_ViewRuleInfo ev_nil_view_rule_info = {0}; thread_static EV_ViewRuleInfoTable *ev_view_rule_info_table = 0; global read_only EV_ViewRuleList ev_nil_view_rule_list = {0}; thread_static EV_AutoViewRuleTable *ev_auto_view_rule_table = 0; +global read_only EV2_Block ev2_nil_block = {&ev2_nil_block, &ev2_nil_block, &ev2_nil_block, &ev2_nil_block, &ev2_nil_block, {0}, 0, {0}, &e_expr_nil, &ev_nil_view_rule_list, &ev_nil_view_rule_info}; //////////////////////////////// //~ rjf: Key Functions @@ -380,6 +456,12 @@ internal EV_ViewRuleList *ev_view_rule_list_copy(Arena *arena, EV_ViewRuleList * internal E_Expr *ev_expr_from_expr_view_rules(Arena *arena, E_Expr *expr, EV_ViewRuleList *view_rules); +//////////////////////////////// +//~ rjf: Block Building (v2) + +internal EV2_BlockTree ev2_block_tree_from_expr(Arena *arena, EV_View *view, String8 string, E_Expr *expr, EV_ViewRuleList *view_rules); +internal EV2_WindowedRowList ev2_windowed_row_list_from_block_tree(Arena *arena, EV_View *view, EV2_BlockTree *block_tree, Rng1U64 visible_range); + //////////////////////////////// //~ rjf: Block Building