diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index e10ca6ca..e018b77c 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -4220,6 +4220,93 @@ df_string_from_simple_typed_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 return result; } +internal String8 +df_escaped_from_raw_string(Arena *arena, String8 raw) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List parts = {0}; + U64 start_split_idx = 0; + for(U64 idx = 0; idx <= raw.size; idx += 1) + { + U8 byte = (idx < raw.size) ? raw.str[idx] : 0; + B32 split = 1; + String8 separator_replace = {0}; + switch(byte) + { + default:{split = 0;}break; + case 0: {}break; + case '\a': {separator_replace = str8_lit("\\a");}break; + case '\b': {separator_replace = str8_lit("\\b");}break; + case '\f': {separator_replace = str8_lit("\\f");}break; + case '\n': {separator_replace = str8_lit("\\n");}break; + case '\r': {separator_replace = str8_lit("\\r");}break; + case '\t': {separator_replace = str8_lit("\\t");}break; + case '\v': {separator_replace = str8_lit("\\v");}break; + case '\\': {separator_replace = str8_lit("\\\\");}break; + case '"': {separator_replace = str8_lit("\\\"");}break; + case '?': {separator_replace = str8_lit("\\?");}break; + } + if(split) + { + String8 substr = str8_substr(raw, r1u64(start_split_idx, idx)); + start_split_idx = idx+1; + str8_list_push(scratch.arena, &parts, substr); + if(separator_replace.size != 0) + { + str8_list_push(scratch.arena, &parts, separator_replace); + } + } + } + StringJoin join = {0}; + String8 result = str8_list_join(arena, &parts, &join); + scratch_end(scratch); + return result; +} + +//- rjf: type info -> expandability/editablity + +internal B32 +df_type_key_is_expandable(E_TypeKey type_key) +{ + B32 result = 0; + for(E_TypeKey t = type_key; !result; t = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(t)))) + { + E_TypeKind kind = e_type_kind_from_key(t); + if(kind == E_TypeKind_Null || kind == E_TypeKind_Function) + { + break; + } + if(kind == E_TypeKind_Struct || + kind == E_TypeKind_Union || + kind == E_TypeKind_Class || + kind == E_TypeKind_Array || + kind == E_TypeKind_Enum) + { + result = 1; + } + } + return result; +} + +internal B32 +df_type_key_is_editable(E_TypeKey type_key) +{ + B32 result = 0; + for(E_TypeKey t = type_key; !result; t = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(t)))) + { + E_TypeKind kind = e_type_kind_from_key(t); + if(kind == E_TypeKind_Null || kind == E_TypeKind_Function) + { + break; + } + if((E_TypeKind_FirstBasic <= kind && kind <= E_TypeKind_LastBasic) || e_type_kind_is_pointer_or_ref(kind)) + { + result = 1; + } + } + return result; +} + //- rjf: writing values back to child processes internal B32 @@ -4533,6 +4620,8 @@ df_eval_viz_block_begin(Arena *arena, DF_EvalVizBlockKind kind, DF_ExpandKey par n->v.parent_key = parent_key; n->v.key = key; n->v.depth = depth; + n->v.expr = &e_expr_nil; + n->v.cfg_table = &df_g_nil_cfg_table; return &n->v; } @@ -4543,15 +4632,15 @@ df_eval_viz_block_split_and_continue(Arena *arena, DF_EvalVizBlockList *list, DF 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->string = split_block->string; + continue_block->expr = split_block->expr; + continue_block->visual_idx_range = continue_block->semantic_idx_range = r1u64(split_idx+1, total_count); + continue_block->cfg_table = split_block->cfg_table; + continue_block->link_bases = split_block->link_bases; + continue_block->members = split_block->members; + continue_block->enum_vals = split_block->enum_vals; + continue_block->fzy_target = split_block->fzy_target; continue_block->fzy_backing_items = split_block->fzy_backing_items; - continue_block->fzy_target = split_block->fzy_target; - 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; } @@ -4566,47 +4655,60 @@ df_eval_viz_block_end(DF_EvalVizBlockList *list, DF_EvalVizBlock *block) } internal void -df_append_viz_blocks_for_parent__rec(Arena *arena, DF_EvalView *eval_view, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, E_Eval eval, E_Member *opt_member, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out) +df_append_viz_blocks_for_parent__rec(Arena *arena, DF_EvalView *eval_view, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, E_Expr *expr, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); - ////////////////////////////// //- rjf: determine if this key is expanded - // DF_ExpandNode *node = df_expand_node_from_key(&eval_view->expand_tree_table, key); - B32 parent_is_expanded = (node != 0 && node->expanded && !e_type_key_match(e_type_key_zero(), eval.type_key)); + B32 parent_is_expanded = (node != 0 && node->expanded); - ////////////////////////////// - //- rjf: apply view rules & resolve eval - // - eval = e_dynamically_typed_eval_from_eval(eval); - eval = df_eval_from_eval_cfg_table(arena, eval, cfg_table); - - ////////////////////////////// - //- rjf: unpack eval - // - E_TypeKey eval_type_key = e_type_unwrap(eval.type_key); - E_TypeKind eval_type_kind = e_type_kind_from_key(eval_type_key); - String8 eval_string = push_str8_copy(arena, string); - - ////////////////////////////// - //- rjf: make and push block for root - // + //- rjf: push block for expression root { DF_EvalVizBlock *block = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_Root, parent_key, key, depth); - block->eval = eval; + block->string = string; + block->expr = expr; block->cfg_table = cfg_table; - block->string = eval_string; 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); - if(opt_member != 0) - { - block->member = e_type_member_copy(arena, opt_member); - } df_eval_viz_block_end(list_out, block); } + //- rjf: determine view rule to generate children blocks + DF_CoreViewRuleSpec *expand_view_rule_spec = df_core_view_rule_spec_from_string(str8_lit("default")); + DF_CfgVal *expand_view_rule_cfg = &df_g_nil_cfg_val; + if(parent_is_expanded) + { + for(DF_CfgVal *val = cfg_table->first_val; + val != 0 && val != &df_g_nil_cfg_val; + val = val->linear_next) + { + DF_CoreViewRuleSpec *spec = df_core_view_rule_spec_from_string(val->string); + if(spec->info.flags & DF_CoreViewRuleSpecInfoFlag_VizBlockProd) + { + expand_view_rule_spec = spec; + expand_view_rule_cfg = val; + break; + } + } + } + + //- rjf: do view rule children block generation, if we have an applicable view rule + if(parent_is_expanded && expand_view_rule_spec != &df_g_nil_core_view_rule_spec) + { + expand_view_rule_spec->info.viz_block_prod(arena, eval_view, parent_key, key, node, string, expr, cfg_table, depth+1, expand_view_rule_cfg, list_out); + } + + scratch_end(scratch); + ProfEnd(); + + //- + //- + //- + // TODO(rjf): OLD vvvvvvvvvvvvvvvvvvvv +#if 0 + ////////////////////////////// //- rjf: (pointers) extract type & info to use for members and/or arrays // @@ -4975,6 +5077,7 @@ df_append_viz_blocks_for_parent__rec(Arena *arena, DF_EvalView *eval_view, DF_Ex scratch_end(scratch); ProfEnd(); +#endif } internal DF_EvalVizBlockList @@ -4983,9 +5086,11 @@ df_eval_viz_block_list_from_eval_view_expr_keys(Arena *arena, DF_EvalView *eval_ ProfBeginFunction(); DF_EvalVizBlockList blocks = {0}; { - E_Eval eval = e_eval_from_string(arena, expr); - U64 expr_comma_pos = str8_find_needle(expr, eval.advance, str8_lit(","), 0); - U64 passthrough_pos = str8_find_needle(expr, eval.advance, str8_lit("--"), 0); + E_TokenArray tokens = e_token_array_from_text(arena, expr); + E_Parse parse = e_parse_expr_from_text_tokens(arena, expr, &tokens); + U64 parse_opl = parse.last_token >= tokens.v + tokens.count ? expr.size : parse.last_token->range.min; + U64 expr_comma_pos = str8_find_needle(expr, parse_opl, str8_lit(","), 0); + U64 passthrough_pos = str8_find_needle(expr, parse_opl, str8_lit("--"), 0); String8List default_view_rules = {0}; if(expr_comma_pos < expr.size && expr_comma_pos < passthrough_pos) { @@ -5017,13 +5122,13 @@ df_eval_viz_block_list_from_eval_view_expr_keys(Arena *arena, DF_EvalView *eval_ } } String8 view_rule_string = df_eval_view_rule_from_key(eval_view, key); - DF_CfgTable view_rule_table = {0}; + DF_CfgTable *view_rule_table = push_array(arena, DF_CfgTable, 1); for(String8Node *n = default_view_rules.first; n != 0; n = n->next) { - df_cfg_table_push_unparsed_string(arena, &view_rule_table, n->string, DF_CfgSrc_User); + df_cfg_table_push_unparsed_string(arena, view_rule_table, n->string, DF_CfgSrc_User); } - df_cfg_table_push_unparsed_string(arena, &view_rule_table, view_rule_string, DF_CfgSrc_User); - df_append_viz_blocks_for_parent__rec(arena, eval_view, parent_key, key, expr, eval, 0, &view_rule_table, 0, &blocks); + df_cfg_table_push_unparsed_string(arena, view_rule_table, view_rule_string, DF_CfgSrc_User); + df_append_viz_blocks_for_parent__rec(arena, eval_view, parent_key, key, expr, parse.expr, view_rule_table, 0, &blocks); } ProfEnd(); return blocks; @@ -5146,10 +5251,145 @@ df_parent_key_from_viz_block_list_row_num(DF_EvalVizBlockList *blocks, S64 row_n return key; } +//- rjf: viz block * index -> expression + +internal E_Expr * +df_expr_from_eval_viz_block_index(Arena *arena, DF_EvalVizBlock *block, U64 index) +{ + E_Expr *result = block->expr; + switch(block->kind) + { + default:{}break; + case DF_EvalVizBlockKind_Members: + { + E_MemberArray *members = &block->members; + if(index < members->count) + { + E_Member *member = &members->v[index]; + E_Expr *dot_expr = e_expr_ref_member_access(arena, block->expr, member->name); + result = dot_expr; + } + }break; + case DF_EvalVizBlockKind_EnumMembers: + { + E_EnumValArray *enum_vals = &block->enum_vals; + if(index < enum_vals->count) + { + E_EnumVal *val = &enum_vals->v[index]; + E_Expr *dot_expr = e_expr_ref_member_access(arena, block->expr, val->name); + result = dot_expr; + } + }break; + case DF_EvalVizBlockKind_Elements: + { + E_Expr *idx_expr = e_expr_ref_array_index(arena, block->expr, index); + result = idx_expr; + }break; + case DF_EvalVizBlockKind_DebugInfoTable: + { + // rjf: unpack row info + FZY_Item *item = &block->fzy_backing_items.v[index]; + DF_ExpandKey parent_key = block->parent_key; + DF_ExpandKey key = block->key; + key.child_num = block->fzy_backing_items.v[index].idx; + + // rjf: determine module to which this item belongs + E_Module *module = e_parse_ctx->primary_module; + U64 base_idx = 0; + { + for(U64 module_idx = 0; module_idx < e_parse_ctx->modules_count; module_idx += 1) + { + U64 all_items_count = 0; + rdi_section_raw_table_from_kind(e_parse_ctx->modules[module_idx].rdi, block->fzy_target, &all_items_count); + if(base_idx <= item->idx && item->idx < base_idx + all_items_count) + { + module = &e_parse_ctx->modules[module_idx]; + break; + } + base_idx += all_items_count; + } + } + + // rjf: build expr + E_Expr *item_expr = &e_expr_nil; + { + RDI_SectionKind section = block->fzy_target; + U64 element_idx = block->fzy_backing_items.v[index].idx - base_idx; + switch(section) + { + default:{}break; + case RDI_SectionKind_Procedures: + { + RDI_Procedure *procedure = rdi_element_from_name_idx(module->rdi, Procedures, element_idx); + RDI_Scope *scope = rdi_element_from_name_idx(module->rdi, Scopes, procedure->root_scope_idx); + U64 voff = *rdi_element_from_name_idx(module->rdi, ScopeVOffData, scope->voff_range_first); + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, voff); + String8 bytecode = e_bytecode_from_oplist(arena, &oplist); + U32 type_idx = procedure->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(module->rdi, TypeNodes, type_idx); + E_TypeKey type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)(module - e_parse_ctx->modules)); + item_expr = e_push_expr(arena, E_ExprKind_LeafBytecode, 0); + item_expr->mode = E_Mode_Offset; + item_expr->space = module->space; + item_expr->type_key = type_key; + item_expr->bytecode = bytecode; + item_expr->string.str = rdi_string_from_idx(module->rdi, procedure->name_string_idx, &item_expr->string.size); + }break; + case RDI_SectionKind_GlobalVariables: + { + RDI_GlobalVariable *gvar = rdi_element_from_name_idx(module->rdi, GlobalVariables, element_idx); + U64 voff = gvar->voff; + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ModuleOff, voff); + String8 bytecode = e_bytecode_from_oplist(arena, &oplist); + U32 type_idx = gvar->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(module->rdi, TypeNodes, type_idx); + E_TypeKey type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)(module - e_parse_ctx->modules)); + item_expr = e_push_expr(arena, E_ExprKind_LeafBytecode, 0); + item_expr->mode = E_Mode_Offset; + item_expr->space = module->space; + item_expr->type_key = type_key; + item_expr->bytecode = bytecode; + item_expr->string.str = rdi_string_from_idx(module->rdi, gvar->name_string_idx, &item_expr->string.size); + }break; + case RDI_SectionKind_ThreadVariables: + { + RDI_ThreadVariable *tvar = rdi_element_from_name_idx(module->rdi, ThreadVariables, element_idx); + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, tvar->tls_off); + String8 bytecode = e_bytecode_from_oplist(arena, &oplist); + U32 type_idx = tvar->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(module->rdi, TypeNodes, type_idx); + E_TypeKey type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)(module - e_parse_ctx->modules)); + item_expr = e_push_expr(arena, E_ExprKind_LeafBytecode, 0); + item_expr->mode = E_Mode_Offset; + item_expr->space = module->space; + item_expr->type_key = type_key; + item_expr->bytecode = bytecode; + item_expr->string.str = rdi_string_from_idx(module->rdi, tvar->name_string_idx, &item_expr->string.size); + }break; + case RDI_SectionKind_UDTs: + { + RDI_UDT *udt = rdi_element_from_name_idx(module->rdi, UDTs, element_idx); + RDI_TypeNode *type_node = rdi_element_from_name_idx(module->rdi, TypeNodes, udt->self_type_idx); + E_TypeKey type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, (U32)(module - e_parse_ctx->modules)); + item_expr = e_push_expr(arena, E_ExprKind_TypeIdent, 0); + item_expr->type_key = type_key; + }break; + } + } + + result = item_expr; + }break; + } + return result; +} + //- rjf: viz row list building internal DF_EvalVizRow * -df_eval_viz_row_list_push_new(Arena *arena, DF_EvalView *eval_view, DF_EvalVizWindowedRowList *rows, DF_EvalVizBlock *block, DF_ExpandKey key, E_Eval eval) +df_eval_viz_row_list_push_new(Arena *arena, DF_EvalView *eval_view, DF_EvalVizWindowedRowList *rows, DF_EvalVizBlock *block, DF_ExpandKey key, E_Expr *expr) { // rjf: push DF_EvalVizRow *row = push_array(arena, DF_EvalVizRow, 1); @@ -5160,48 +5400,9 @@ df_eval_viz_row_list_push_new(Arena *arena, DF_EvalView *eval_view, DF_EvalVizWi row->depth = block->depth; row->parent_key = block->parent_key; row->key = key; - row->eval = eval; row->size_in_rows = 1; - - // rjf: determine exandability, editability - if(e_type_kind_from_key(eval.type_key) != E_TypeKind_Null) - { - for(E_TypeKey t = eval.type_key;; t = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(t)))) - { - E_TypeKind kind = e_type_kind_from_key(t); - if(kind == E_TypeKind_Null) - { - break; - } - if(eval.mode != E_Mode_Null && ((E_TypeKind_FirstBasic <= kind && kind <= E_TypeKind_LastBasic) || kind == E_TypeKind_Ptr || kind == E_TypeKind_LRef || kind == E_TypeKind_RRef)) - { - row->flags |= DF_EvalVizRowFlag_CanEditValue; - } - if(eval.mode == E_Mode_Null && kind == E_TypeKind_Enum) - { - row->flags |= DF_EvalVizRowFlag_CanExpand; - } - if(kind == E_TypeKind_Struct || - kind == E_TypeKind_Union || - kind == E_TypeKind_Class || - kind == E_TypeKind_Array) - { - row->flags |= DF_EvalVizRowFlag_CanExpand; - } - if(row->flags & DF_EvalVizRowFlag_CanExpand) - { - break; - } - if(eval.mode == E_Mode_Null) - { - break; - } - if(kind == E_TypeKind_Function) - { - break; - } - } - } + row->string = block->string; + row->expr = expr; // rjf: fill view-rule-derived info { @@ -5258,7 +5459,6 @@ df_eval_viz_row_list_push_new(Arena *arena, DF_EvalView *eval_view, DF_EvalVizWi } // rjf: fill - if(expandability_required) { row->flags |= DF_EvalVizRowFlag_CanExpand; } row->cfg_table = cfg_table; row->value_ui_rule_node = value_ui_rule_node; row->value_ui_rule_spec = value_ui_rule_spec; @@ -5269,6 +5469,183 @@ df_eval_viz_row_list_push_new(Arena *arena, DF_EvalView *eval_view, DF_EvalVizWi return row; } +internal DF_EvalVizWindowedRowList +df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DF_EvalView *eval_view, Rng1S64 visible_range, DF_EvalVizBlockList *blocks) +{ + ProfBeginFunction(); + Temp scratch = scratch_begin(&arena, 1); + + ////////////////////////////// + //- rjf: produce windowed rows, per block + // + U64 visual_idx_off = 0; + U64 semantic_idx_off = 0; + DF_EvalVizWindowedRowList list = {0}; + for(DF_EvalVizBlockNode *n = blocks->first; n != 0; n = n->next) + { + DF_EvalVizBlock *block = &n->v; + + ////////////////////////////// + //- rjf: extract block info + // + U64 block_num_visual_rows = dim_1u64(block->visual_idx_range); + U64 block_num_semantic_rows = dim_1u64(block->semantic_idx_range); + Rng1S64 block_visual_range = r1s64(visual_idx_off, visual_idx_off + block_num_visual_rows); + Rng1S64 block_semantic_range = r1s64(semantic_idx_off, semantic_idx_off + block_num_semantic_rows); + + ////////////////////////////// + //- rjf: get skip/chop of block's index range + // + U64 num_skipped_visual = 0; + U64 num_chopped_visual = 0; + { + if(visible_range.min > block_visual_range.min) + { + num_skipped_visual = (visible_range.min - block_visual_range.min); + num_skipped_visual = Min(num_skipped_visual, block_num_visual_rows); + } + if(visible_range.max < block_visual_range.max) + { + num_chopped_visual = (block_visual_range.max - visible_range.max); + num_chopped_visual = Min(num_chopped_visual, block_num_visual_rows); + } + } + + ////////////////////////////// + //- rjf: get visible idx range & invisible counts + // + Rng1U64 visible_idx_range = block->visual_idx_range; + { + visible_idx_range.min += num_skipped_visual; + visible_idx_range.max -= num_chopped_visual; + } + + ////////////////////////////// + //- rjf: sum & advance + // + 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; + } + visual_idx_off += block_num_visual_rows; + semantic_idx_off += block_num_semantic_rows; + + ////////////////////////////// + //- rjf: produce rows, depending on block's kind + // + if(visible_idx_range.max > visible_idx_range.min) switch(block->kind) + { + default:{}break; + + ////////////////////////////// + //- rjf: single rows, piping in info from the originating block + // + case DF_EvalVizBlockKind_Null: + case DF_EvalVizBlockKind_Root: + { + df_eval_viz_row_list_push_new(arena, eval_view, &list, block, block->key, block->expr); + }break; + + ////////////////////////////// + //- rjf: canvas -> produce blank row, sized by the idx range specified in the block + // + case DF_EvalVizBlockKind_Canvas: + if(num_skipped_visual < block_num_visual_rows) + { + DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(block->parent_key), 1); + DF_EvalVizRow *row = df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, block->expr); + row->size_in_rows = dim_1u64(intersect_1u64(visible_idx_range, r1u64(0, dim_1u64(block->visual_idx_range)))); + row->skipped_size_in_rows= (visible_idx_range.min > block->visual_idx_range.min) ? visible_idx_range.min - block->visual_idx_range.min : 0; + row->chopped_size_in_rows= (visible_idx_range.max < block->visual_idx_range.max) ? block->visual_idx_range.max - visible_idx_range.max : 0; + }break; + + ////////////////////////////// + //- rjf: all elements of a debug info table -> produce rows for visible range + // + case DF_EvalVizBlockKind_DebugInfoTable: + for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1) + { + FZY_Item *item = &block->fzy_backing_items.v[idx]; + DF_ExpandKey parent_key = block->parent_key; + DF_ExpandKey key = block->key; + key.child_num = block->fzy_backing_items.v[idx].idx; + E_Expr *row_expr = df_expr_from_eval_viz_block_index(arena, block, idx); + df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, row_expr); + }break; + + ////////////////////////////// + //- rjf: members/elements/enum-members + // + case DF_EvalVizBlockKind_Members: + case DF_EvalVizBlockKind_EnumMembers: + case DF_EvalVizBlockKind_Elements: + { + for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1) + { + DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(block->parent_key), idx+1); + E_Expr *expr = df_expr_from_eval_viz_block_index(arena, block, idx); + df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, expr); + } + }break; + } + } + scratch_end(scratch); + ProfEnd(); + return list; +} + +//- rjf: viz row -> strings + +internal String8 +df_expr_string_from_viz_row(Arena *arena, DF_EvalVizRow *row) +{ + String8 result = row->string; + if(result.size == 0) switch(row->expr->kind) + { + default: + { + result = e_string_from_expr(arena, row->expr); + }break; + case E_ExprKind_ArrayIndex: + { + result = push_str8f(arena, "[%S]", e_string_from_expr(arena, row->expr->last)); + }break; + case E_ExprKind_LeafMember: + { + result = push_str8f(arena, ".%S", e_string_from_expr(arena, row->expr->last)); + }break; + } + return result; +} + +//- rjf: viz row -> expandability/editability + +internal B32 +df_viz_row_is_expandable(DF_EvalVizRow *row) +{ + B32 result = (row->expand_ui_rule_spec != &df_g_nil_gfx_view_rule_spec && row->expand_ui_rule_spec != 0); + if(!result) + { + Temp scratch = scratch_begin(0, 0); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, row->expr); + result = df_type_key_is_expandable(irtree.type_key); + scratch_end(scratch); + } + return result; +} + +internal B32 +df_viz_row_is_editable(DF_EvalVizRow *row) +{ + B32 result = 0; + Temp scratch = scratch_begin(0, 0); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, row->expr); + result = df_type_key_is_editable(irtree.type_key); + scratch_end(scratch); + return result; +} + //////////////////////////////// //~ rjf: Main State Accessors/Mutators diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index d3bdce76..d8108357 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -179,7 +179,17 @@ typedef struct DF_EvalVizBlockList DF_EvalVizBlockList; #define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(name) E_Eval name(Arena *arena, E_Eval eval, DF_CfgVal *val) #define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(name) df_core_view_rule_eval_resolution__##name #define DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(name) internal DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(name)) -#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, DF_EvalView *eval_view, E_Eval eval, String8 string, DF_CfgTable *cfg_table, DF_ExpandKey parent_key, DF_ExpandKey key, S32 depth, DF_CfgNode *cfg, struct DF_EvalVizBlockList *out) +#define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(name) void name(Arena *arena, \ +DF_EvalView *eval_view, \ +DF_ExpandKey parent_key, \ +DF_ExpandKey key, \ +DF_ExpandNode *expand_node, \ +String8 string, \ +E_Expr *expr, \ +DF_CfgTable *cfg_table, \ +S32 depth, \ +DF_CfgVal *cfg_val, \ +struct DF_EvalVizBlockList *out) #define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(name) df_core_view_rule_viz_block_prod__##name #define DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(name) internal DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_SIG(DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(name)) typedef DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_SIG(DF_CoreViewRuleEvalResolutionHookFunctionType); @@ -683,7 +693,6 @@ typedef enum DF_EvalVizBlockKind DF_EvalVizBlockKind_Members, // members of struct, class, union DF_EvalVizBlockKind_EnumMembers, // members of enum DF_EvalVizBlockKind_Elements, // elements of array - DF_EvalVizBlockKind_Links, // flattened nodes in a linked list DF_EvalVizBlockKind_Canvas, // escape hatch for arbitrary UI DF_EvalVizBlockKind_DebugInfoTable, // block of filtered debug info table elements DF_EvalVizBlockKind_COUNT, @@ -700,20 +709,20 @@ struct DF_EvalVizBlock S32 depth; // rjf: evaluation info - E_Eval eval; String8 string; - E_Member *member; + E_Expr *expr; // rjf: info about ranges that this block spans Rng1U64 visual_idx_range; Rng1U64 semantic_idx_range; - RDI_SectionKind fzy_target; - FZY_ItemArray fzy_backing_items; // rjf: visualization config extensions DF_CfgTable *cfg_table; - E_TypeKey link_member_type_key; - U64 link_member_off; + DF_EvalLinkBaseChunkList *link_bases; + E_MemberArray members; + E_EnumValArray enum_vals; + RDI_SectionKind fzy_target; + FZY_ItemArray fzy_backing_items; }; typedef struct DF_EvalVizBlockNode DF_EvalVizBlockNode; @@ -748,43 +757,30 @@ enum DF_EvalVizStringFlag_ReadOnlyDisplayRules = (1<<0), }; -typedef U32 DF_EvalVizRowFlags; -enum -{ - DF_EvalVizRowFlag_CanExpand = (1<<0), - DF_EvalVizRowFlag_CanEditValue = (1<<1), - DF_EvalVizRowFlag_Canvas = (1<<2), - DF_EvalVizRowFlag_ExprIsSpecial= (1<<3), -}; - typedef struct DF_EvalVizRow DF_EvalVizRow; struct DF_EvalVizRow { DF_EvalVizRow *next; - DF_EvalVizRowFlags flags; - // rjf: block info + // rjf: block hierarchy info S32 depth; DF_ExpandKey parent_key; DF_ExpandKey key; - // rjf: evaluation artifacts - E_Eval eval; - E_Member *member; - - // rjf: basic visualization contents - DF_CfgTable *cfg_table; - String8 display_expr; - String8 edit_expr; - - // rjf: variable-size & hook info + // rjf: row size/scroll info U64 size_in_rows; U64 skipped_size_in_rows; U64 chopped_size_in_rows; + + // rjf: evaluation expression + String8 string; + E_Member *member; + E_Expr *expr; + + // rjf: view rule attachments + DF_CfgTable *cfg_table; struct DF_GfxViewRuleSpec *expand_ui_rule_spec; struct DF_CfgNode *expand_ui_rule_node; - - // rjf: value area override view rule spec struct DF_GfxViewRuleSpec *value_ui_rule_spec; struct DF_CfgNode *value_ui_rule_node; }; @@ -1221,6 +1217,7 @@ read_only global DF_CmdSpec df_g_nil_cmd_spec = {0}; read_only global DF_CoreViewRuleSpec df_g_nil_core_view_rule_spec = {0}; read_only global DF_CfgNode df_g_nil_cfg_node = {&df_g_nil_cfg_node, &df_g_nil_cfg_node, &df_g_nil_cfg_node, &df_g_nil_cfg_node}; read_only global DF_CfgVal df_g_nil_cfg_val = {&df_g_nil_cfg_val, &df_g_nil_cfg_val, &df_g_nil_cfg_node, &df_g_nil_cfg_node}; +read_only global DF_CfgTable df_g_nil_cfg_table = {0, 0, 0, &df_g_nil_cfg_val, &df_g_nil_cfg_val}; read_only global DF_Entity df_g_nil_entity = { // rjf: tree links @@ -1587,6 +1584,11 @@ internal String8 df_string_from_ascii_value(Arena *arena, U8 val); internal String8 df_string_from_hresult_facility_code(U32 code); internal String8 df_string_from_hresult_code(U32 code); internal String8 df_string_from_simple_typed_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 radix, E_Eval eval); +internal String8 df_escaped_from_raw_string(Arena *arena, String8 raw); + +//- rjf: type info -> expandability/editablity +internal B32 df_type_key_is_expandable(E_TypeKey type_key); +internal B32 df_type_key_is_editable(E_TypeKey type_key); //- rjf: writing values back to child processes internal B32 df_commit_eval_value(E_Eval dst_eval, E_Eval src_eval); @@ -1601,7 +1603,7 @@ internal DF_EvalLinkBaseArray df_eval_link_base_array_from_chunk_list(Arena *are 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, DF_EvalView *view, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, E_Eval eval, E_Member *opt_member, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out); +internal void df_append_viz_blocks_for_parent__rec(Arena *arena, DF_EvalView *view, DF_ExpandKey parent_key, DF_ExpandKey key, String8 string, E_Expr *expr, DF_CfgTable *cfg_table, S32 depth, DF_EvalVizBlockList *list_out); internal DF_EvalVizBlockList df_eval_viz_block_list_from_eval_view_expr_keys(Arena *arena, DF_EvalView *eval_view, String8 expr, DF_ExpandKey parent_key, DF_ExpandKey key); internal void df_eval_viz_block_list_concat__in_place(DF_EvalVizBlockList *dst, DF_EvalVizBlockList *to_push); @@ -1610,8 +1612,19 @@ internal S64 df_row_num_from_viz_block_list_key(DF_EvalVizBlockList *blocks, DF_ internal DF_ExpandKey df_key_from_viz_block_list_row_num(DF_EvalVizBlockList *blocks, S64 row_num); internal DF_ExpandKey df_parent_key_from_viz_block_list_row_num(DF_EvalVizBlockList *blocks, S64 row_num); +//- rjf: viz block * index -> expression +internal E_Expr *df_expr_from_eval_viz_block_index(Arena *arena, DF_EvalVizBlock *block, U64 index); + //- rjf: viz row list building -internal DF_EvalVizRow *df_eval_viz_row_list_push_new(Arena *arena, DF_EvalView *eval_view, DF_EvalVizWindowedRowList *rows, DF_EvalVizBlock *block, DF_ExpandKey key, E_Eval eval); +internal DF_EvalVizRow *df_eval_viz_row_list_push_new(Arena *arena, DF_EvalView *eval_view, DF_EvalVizWindowedRowList *rows, DF_EvalVizBlock *block, DF_ExpandKey key, E_Expr *expr); +internal DF_EvalVizWindowedRowList df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DF_EvalView *eval_view, Rng1S64 visible_range, DF_EvalVizBlockList *blocks); + +//- rjf: viz row -> strings +internal String8 df_expr_string_from_viz_row(Arena *arena, DF_EvalVizRow *row); + +//- rjf: viz row -> expandability/editability +internal B32 df_viz_row_is_expandable(DF_EvalVizRow *row); +internal B32 df_viz_row_is_editable(DF_EvalVizRow *row); //////////////////////////////// //~ rjf: Main State Accessors/Mutators diff --git a/src/df/core/df_core.mdesk b/src/df/core/df_core.mdesk index bd556157..3751ded6 100644 --- a/src/df/core/df_core.mdesk +++ b/src/df/core/df_core.mdesk @@ -524,7 +524,7 @@ DF_CoreCmdTable:// | | | | @table(name name_lower string ih ex er vb display_name docs schema description) DF_CoreViewRuleTable: { - {Null null "" - - - - "" - "" "" } + {Default default "default" - - - x "Default" - "" "" } {Array array "array" - - x - "Array" x "x:{expr}" "Specifies that a pointer points to N elements, rather than only 1." } {Slice slice "slice" - - x - "Slice" x "" "Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer." } {List list "list" - - - x "List" x "x:{member}" "Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list." } diff --git a/src/df/core/generated/df_core.meta.c b/src/df/core/generated/df_core.meta.c index 963f9a64..d94ee73a 100644 --- a/src/df/core/generated/df_core.meta.c +++ b/src/df/core/generated/df_core.meta.c @@ -484,7 +484,7 @@ DF_CmdSpecInfo df_g_core_cmd_kind_spec_info_table[222] = DF_CoreViewRuleSpecInfo df_g_core_view_rule_spec_info_table[18] = { -{str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), 0, 0, }, +{str8_lit_comp("default"), str8_lit_comp("Default"), str8_lit_comp(""), str8_lit_comp(""), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(default) , }, {str8_lit_comp("array"), str8_lit_comp("Array"), str8_lit_comp("x:{expr}"), str8_lit_comp("Specifies that a pointer points to N elements, rather than only 1."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*1)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(array) , 0, }, {str8_lit_comp("slice"), str8_lit_comp("Slice"), str8_lit_comp(""), str8_lit_comp("Specifies that a pointer within a struct, also containing an integer, points to the number of elements encoded by the integer."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*1)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*0), DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_NAME(slice) , 0, }, {str8_lit_comp("list"), str8_lit_comp("List"), str8_lit_comp("x:{member}"), str8_lit_comp("Specifies that some struct, union, or class forms the top of a linked list, and the member which points at the following element in the list."), (DF_CoreViewRuleSpecInfoFlag_Inherited*0)|(DF_CoreViewRuleSpecInfoFlag_Expandable*0)|(DF_CoreViewRuleSpecInfoFlag_EvalResolution*0)|(DF_CoreViewRuleSpecInfoFlag_VizBlockProd*1), 0, DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_NAME(list) , }, diff --git a/src/df/core/generated/df_core.meta.h b/src/df/core/generated/df_core.meta.h index ae8d5625..7fa1ad37 100644 --- a/src/df/core/generated/df_core.meta.h +++ b/src/df/core/generated/df_core.meta.h @@ -351,7 +351,7 @@ DF_IconKind_COUNT, typedef enum DF_CoreViewRuleKind { -DF_CoreViewRuleKind_Null, +DF_CoreViewRuleKind_Default, DF_CoreViewRuleKind_Array, DF_CoreViewRuleKind_Slice, DF_CoreViewRuleKind_List, @@ -433,6 +433,7 @@ U64 inline_depth; DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(array); DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(slice); DF_CORE_VIEW_RULE_EVAL_RESOLUTION_FUNCTION_DEF(bswap); +DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(default); DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(list); DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(only); DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(omit); diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 92fc00a7..b149c578 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -6134,7 +6134,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(parent_key), 1); DF_EvalVizBlockList viz_blocks = df_eval_viz_block_list_from_eval_view_expr_keys(scratch.arena, eval_view, expr, parent_key, key); U32 default_radix = (eval.space == E_Space_Regs ? 16 : 10); - DF_EvalVizWindowedRowList viz_rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, default_radix, ui_top_font(), ui_top_font_size(), r1s64(0, 50), &viz_blocks); + DF_EvalVizWindowedRowList viz_rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, r1s64(0, 50), &viz_blocks); //- rjf: animate { @@ -6210,27 +6210,31 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) for(DF_EvalVizRow *row = viz_rows.first; row != 0; row = row->next) { //- rjf: unpack row - String8 row_edit_value = df_value_string_from_eval(scratch.arena, 0, default_radix, ui_top_font(), ui_top_font_size(), 500.f, row->eval, row->member, row->cfg_table); - String8 row_display_value = df_value_string_from_eval(scratch.arena, DF_EvalVizStringFlag_ReadOnlyDisplayRules, default_radix, ui_top_font(), ui_top_font_size(), 500.f, row->eval, row->member, row->cfg_table); + E_Eval row_eval = e_eval_from_expr(scratch.arena, row->expr); + String8 row_expr_string = df_expr_string_from_viz_row(scratch.arena, row); + String8 row_edit_value = df_value_string_from_eval(scratch.arena, 0, default_radix, ui_top_font(), ui_top_font_size(), 500.f, row_eval, row->cfg_table); + String8 row_display_value = df_value_string_from_eval(scratch.arena, DF_EvalVizStringFlag_ReadOnlyDisplayRules, default_radix, ui_top_font(), ui_top_font_size(), 500.f, row_eval, row->cfg_table); + B32 row_is_editable = df_type_key_is_editable(row_eval.type_key); + B32 row_is_expandable = df_type_key_is_expandable(row_eval.type_key); //- rjf: calculate width of exp row if(row == viz_rows.first) { - expr_column_width_px = f_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), row->display_expr).x + ui_top_font_size()*2.5f; + expr_column_width_px = f_dim_from_tag_size_string(ui_top_font(), ui_top_font_size(), 0, ui_top_tab_size(), row_display_value).x + ui_top_font_size()*2.5f; expr_column_width_px = Max(expr_column_width_px, ui_top_font_size()*10.f); } //- rjf: determine if row's data is fresh B32 row_is_fresh = 0; - switch(row->eval.mode) + switch(row_eval.mode) { default:{}break; case E_Mode_Offset: { // TODO(rjf): @spaces pick the right process from the eval's space - U64 size = e_type_byte_size_from_key(row->eval.type_key); + U64 size = e_type_byte_size_from_key(row_eval.type_key); size = Min(size, 64); - Rng1U64 vaddr_rng = r1u64(row->eval.value.u64, row->eval.value.u64+size); + Rng1U64 vaddr_rng = r1u64(row_eval.value.u64, row_eval.value.u64+size); CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, vaddr_rng, 0); for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1) { @@ -6250,13 +6254,13 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) ui_spacer(ui_em(1.5f*row->depth, 1.f)); U64 row_hash = df_hash_from_expand_key(row->key); B32 row_is_expanded = df_expand_key_is_set(&eval_view->expand_tree_table, row->key); - if(row->flags & DF_EvalVizRowFlag_CanExpand) + if(row_is_expandable) UI_PrefWidth(ui_em(1.5f, 1)) UI_Flags(UI_BoxFlag_DrawSideLeft*(row->depth>0)) if(ui_pressed(ui_expanderf(row_is_expanded, "###%I64x_%I64x_is_expanded", row->key.parent_hash, row->key.child_num))) { df_expand_set_expansion(eval_view->arena, &eval_view->expand_tree_table, row->parent_key, row->key, !row_is_expanded); } - if(!(row->flags & DF_EvalVizRowFlag_CanExpand)) + if(!row_is_expandable) { UI_PrefWidth(ui_em(1.5f, 1)) UI_Flags(UI_BoxFlag_DrawSideLeft*(row->depth>0) | UI_BoxFlag_DrawTextWeak) @@ -6265,9 +6269,9 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) } UI_WidthFill UI_TextRasterFlags(df_raster_flags_from_slot(ws, DF_FontSlot_Code)) { - UI_PrefWidth(ui_px(expr_column_width_px, 1.f)) df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), row->display_expr); + UI_PrefWidth(ui_px(expr_column_width_px, 1.f)) df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), row_expr_string); ui_spacer(ui_em(1.5f, 1.f)); - if(row->flags & DF_EvalVizRowFlag_CanEditValue) + if(row_is_editable) { if(row_is_fresh) { @@ -6287,7 +6291,7 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) { String8 commit_string = str8(ws->hover_eval_txt_buffer, ws->hover_eval_txt_size); E_Eval write_eval = e_eval_from_string(scratch.arena, commit_string); - B32 success = df_commit_eval_value(row->eval, write_eval); + B32 success = df_commit_eval_value(row_eval, write_eval); if(success == 0) { DF_CmdParams params = df_cmd_params_from_window(ws); @@ -8283,719 +8287,333 @@ df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdList *cmds) //////////////////////////////// //~ rjf: Eval Viz -internal String8 -df_escaped_from_raw_string(Arena *arena, String8 raw) -{ - Temp scratch = scratch_begin(&arena, 1); - String8List parts = {0}; - U64 start_split_idx = 0; - for(U64 idx = 0; idx <= raw.size; idx += 1) - { - U8 byte = (idx < raw.size) ? raw.str[idx] : 0; - B32 split = 1; - String8 separator_replace = {0}; - switch(byte) - { - default:{split = 0;}break; - case 0: {}break; - case '\a': {separator_replace = str8_lit("\\a");}break; - case '\b': {separator_replace = str8_lit("\\b");}break; - case '\f': {separator_replace = str8_lit("\\f");}break; - case '\n': {separator_replace = str8_lit("\\n");}break; - case '\r': {separator_replace = str8_lit("\\r");}break; - case '\t': {separator_replace = str8_lit("\\t");}break; - case '\v': {separator_replace = str8_lit("\\v");}break; - case '\\': {separator_replace = str8_lit("\\\\");}break; - case '"': {separator_replace = str8_lit("\\\"");}break; - case '?': {separator_replace = str8_lit("\\?");}break; - } - if(split) - { - String8 substr = str8_substr(raw, r1u64(start_split_idx, idx)); - start_split_idx = idx+1; - str8_list_push(scratch.arena, &parts, substr); - if(separator_replace.size != 0) - { - str8_list_push(scratch.arena, &parts, separator_replace); - } - } - } - StringJoin join = {0}; - String8 result = str8_list_join(arena, &parts, &join); - scratch_end(scratch); - return result; -} - -internal String8List -df_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, S32 depth, E_Eval eval, E_Member *opt_member, DF_CfgTable *cfg_table) +internal F32 +df_append_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, S32 depth, E_Eval eval, DF_CfgTable *cfg_table, String8List *out) { ProfBeginFunction(); - String8List list = {0}; + Temp scratch = scratch_begin(&arena, 1); F32 space_taken = 0; - //- rjf: type path -> empty - if(eval.mode == E_Mode_Null && !e_type_key_match(e_type_key_zero(), eval.type_key)) + //- rjf: unpack view rules + U32 radix = default_radix; + DF_CfgVal *dec_cfg = df_cfg_val_from_string(cfg_table, str8_lit("dec")); + DF_CfgVal *hex_cfg = df_cfg_val_from_string(cfg_table, str8_lit("hex")); + DF_CfgVal *bin_cfg = df_cfg_val_from_string(cfg_table, str8_lit("bin")); + DF_CfgVal *oct_cfg = df_cfg_val_from_string(cfg_table, str8_lit("oct")); + U64 best_insertion_stamp = Max(dec_cfg->insertion_stamp, Max(hex_cfg->insertion_stamp, Max(bin_cfg->insertion_stamp, oct_cfg->insertion_stamp))); + if(dec_cfg != &df_g_nil_cfg_val && dec_cfg->insertion_stamp == best_insertion_stamp) { radix = 10; } + if(hex_cfg != &df_g_nil_cfg_val && hex_cfg->insertion_stamp == best_insertion_stamp) { radix = 16; } + if(bin_cfg != &df_g_nil_cfg_val && bin_cfg->insertion_stamp == best_insertion_stamp) { radix = 2; } + if(oct_cfg != &df_g_nil_cfg_val && oct_cfg->insertion_stamp == best_insertion_stamp) { radix = 8; } + B32 no_addr = (df_cfg_val_from_string(cfg_table, str8_lit("no_addr")) != &df_g_nil_cfg_val) && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules); + B32 has_array = (df_cfg_val_from_string(cfg_table, str8_lit("array")) != &df_g_nil_cfg_val); + + //- rjf: member evaluations -> display member info + if(eval.mode == E_Mode_Null && !e_type_key_match(e_type_key_zero(), eval.type_key) && eval.expr->kind == E_ExprKind_MemberAccess) { - if(opt_member != 0) + E_Eval lhs_eval = e_eval_from_expr(scratch.arena, eval.expr->first); + E_MemberArray lhs_members = e_type_data_members_from_key(scratch.arena, lhs_eval.type_key); + E_Member *member = e_type_member_from_array_name(&lhs_members, eval.expr->first->next->string); + if(member != 0) { - U64 member_byte_size = e_type_byte_size_from_key(opt_member->type_key); - str8_list_pushf(arena, &list, "member (%I64u offset, %I64u byte%s)", opt_member->off, member_byte_size, member_byte_size == 1 ? "s" : ""); - } - else - { - String8 basic_type_kind_string = e_kind_basic_string_table[e_type_kind_from_key(eval.type_key)]; - U64 byte_size = e_type_byte_size_from_key(eval.type_key); - str8_list_pushf(arena, &list, "%S (%I64u byte%s)", basic_type_kind_string, byte_size, byte_size == 1 ? "s" : ""); + U64 member_byte_size = e_type_byte_size_from_key(eval.type_key); + String8 offset_string = str8_from_u64(arena, member->off, radix, 0, 0); + String8 size_string = str8_from_u64(arena, member_byte_size, radix, 0, 0); + str8_list_pushf(arena, out, "member (%S offset, %S byte%s)", offset_string, size_string, member_byte_size == 1 ? "" : "s"); } } - //- rjf: non-type path: descend recursively & produce single-line value strings - else if(max_size > 0) + //- rjf: type evaluations -> display type basic information + else if(eval.mode == E_Mode_Null && !e_type_key_match(e_type_key_zero(), eval.type_key) && eval.expr->kind != E_ExprKind_MemberAccess) { - E_TypeKind eval_type_kind = e_type_kind_from_key(e_type_unwrap(eval.type_key)); - U32 radix = default_radix; - DF_CfgVal *dec_cfg = df_cfg_val_from_string(cfg_table, str8_lit("dec")); - DF_CfgVal *hex_cfg = df_cfg_val_from_string(cfg_table, str8_lit("hex")); - DF_CfgVal *bin_cfg = df_cfg_val_from_string(cfg_table, str8_lit("bin")); - DF_CfgVal *oct_cfg = df_cfg_val_from_string(cfg_table, str8_lit("oct")); - U64 best_insertion_stamp = Max(dec_cfg->insertion_stamp, Max(hex_cfg->insertion_stamp, Max(bin_cfg->insertion_stamp, oct_cfg->insertion_stamp))); - if(dec_cfg != &df_g_nil_cfg_val && dec_cfg->insertion_stamp == best_insertion_stamp) { radix = 10; } - if(hex_cfg != &df_g_nil_cfg_val && hex_cfg->insertion_stamp == best_insertion_stamp) { radix = 16; } - if(bin_cfg != &df_g_nil_cfg_val && bin_cfg->insertion_stamp == best_insertion_stamp) { radix = 2; } - if(oct_cfg != &df_g_nil_cfg_val && oct_cfg->insertion_stamp == best_insertion_stamp) { radix = 8; } - switch(eval_type_kind) + String8 basic_type_kind_string = e_kind_basic_string_table[e_type_kind_from_key(eval.type_key)]; + U64 byte_size = e_type_byte_size_from_key(eval.type_key); + String8 size_string = str8_from_u64(arena, byte_size, radix, 0, 0); + str8_list_pushf(arena, out, "%S (%S byte%s)", basic_type_kind_string, size_string, byte_size == 1 ? "" : "s"); + } + + //- rjf: value/offset evaluations + else if(max_size > 0) switch(e_type_kind_from_key(eval.type_key)) + { + //- rjf: default - leaf cases + default: { - //- rjf: default - leaf cases - default: - { - E_Eval value_eval = e_value_eval_from_eval(eval); - String8 string = df_string_from_simple_typed_eval(arena, flags, radix, value_eval); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, string).x; - str8_list_push(arena, &list, string); - }break; + E_Eval value_eval = e_value_eval_from_eval(eval); + String8 string = df_string_from_simple_typed_eval(arena, flags, radix, value_eval); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, string).x; + str8_list_push(arena, out, string); + }break; + + //- rjf: pointers + case E_TypeKind_Function: + case E_TypeKind_Ptr: + case E_TypeKind_LRef: + case E_TypeKind_RRef: + { + // rjf: unpack type info + E_TypeKind type_kind = e_type_kind_from_key(eval.type_key); + E_TypeKey direct_type_key = e_type_ptee_from_key(eval.type_key); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - //- rjf: pointers - case E_TypeKind_Function: - case E_TypeKind_Ptr: - case E_TypeKind_LRef: - case E_TypeKind_RRef: - { - // rjf: determine ptr value omission - DF_CfgVal *noaddr_cfg = df_cfg_val_from_string(cfg_table, str8_lit("no_addr")); - B32 no_addr = (noaddr_cfg != &df_g_nil_cfg_val) && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules); - - // rjf: determine presence of array view rule -> omit c-string fastpath - DF_CfgVal *array_cfg = df_cfg_val_from_string(cfg_table, str8_lit("array")); - B32 has_array = (array_cfg != &df_g_nil_cfg_val); - - // rjf: get ptr value - E_Eval value_eval = e_value_eval_from_eval(eval); - - // rjf: get pointed-at info - E_TypeKind type_kind = e_type_kind_from_key(eval.type_key); - E_TypeKey direct_type_key = e_type_ptee_from_key(eval.type_key); - E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - B32 direct_type_has_content = (direct_type_kind != E_TypeKind_Null && direct_type_kind != E_TypeKind_Void && value_eval.value.u64 != 0); - B32 direct_type_is_string = (direct_type_kind != E_TypeKind_Null && value_eval.value.u64 != 0 && - (E_TypeKind_Char8 <= direct_type_kind && direct_type_kind <= E_TypeKind_UChar32)); - DF_Entity *thread = df_entity_from_handle(df_interact_regs()->thread); - DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); - String8 symbol_name = df_symbol_name_from_process_vaddr(arena, process, value_eval.value.u64, 1); - - // rjf: display ptr value - B32 did_ptr_value = 0; - if(!no_addr || (direct_type_has_content == 0 && direct_type_is_string == 0)) - { - did_ptr_value = 1; - String8 string = df_string_from_simple_typed_eval(arena, flags, radix, value_eval); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, string).x; - str8_list_push(arena, &list, string); - } - - // rjf: arrow - if(did_ptr_value && (direct_type_has_content || symbol_name.size != 0) && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules)) - { - String8 arrow = str8_lit(" -> "); - str8_list_push(arena, &list, arrow); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, arrow).x; - } - - // rjf: special-case: strings - if(!has_array && - direct_type_is_string && - (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules)) - { - // TODO(rjf): @spaces pick correct space - U64 string_memory_addr = value_eval.value.u64; - U64 element_size = e_type_byte_size_from_key(direct_type_key); - CTRL_ProcessMemorySlice text_slice = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, string_memory_addr, 256, element_size, 0); - String8 raw_text = {0}; - switch(element_size) - { - default:{raw_text = text_slice.data;}break; - case 2: {raw_text = str8_from_16(arena, str16((U16 *)text_slice.data.str, text_slice.data.size/sizeof(U16)));}break; - case 4: {raw_text = str8_from_32(arena, str32((U32 *)text_slice.data.str, text_slice.data.size/sizeof(U32)));}break; - } - String8 text = df_escaped_from_raw_string(arena, raw_text); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, text).x; - space_taken += 2*f_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("\"")).x; - str8_list_push(arena, &list, str8_lit("\"")); - str8_list_push(arena, &list, text); - str8_list_push(arena, &list, str8_lit("\"")); - } - - // rjf: special-case: symbols - else if((flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) && symbol_name.size != 0 && - (type_kind == E_TypeKind_Function || - direct_type_kind == E_TypeKind_Function || - direct_type_kind == E_TypeKind_Void)) - { - str8_list_push(arena, &list, symbol_name); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, symbol_name).x; - } - - // rjf: descend to pointed-at thing - else if(direct_type_has_content && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules)) - { - if(depth < 4) - { - E_Eval pted_eval = zero_struct; - pted_eval.type_key = direct_type_key; - pted_eval.mode = E_Mode_Offset; - pted_eval.space = value_eval.space; - pted_eval.value = value_eval.value; - String8List pted_strs = df_value_strings_from_eval(arena, flags, default_radix, font, font_size, max_size-space_taken, depth+1, pted_eval, opt_member, cfg_table); - if(pted_strs.total_size == 0) - { - String8 unknown = str8_lit("???"); - str8_list_push(arena, &list, unknown); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, unknown).x; - } - else - { - space_taken += f_dim_from_tag_size_string_list(font, font_size, 0, 0, pted_strs).x; - str8_list_concat_in_place(&list, &pted_strs); - } - } - else - { - String8 ellipses = str8_lit("..."); - str8_list_push(arena, &list, ellipses); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; - } - } - }break; + // rjf: unpack info about pointer destination + E_Eval value_eval = e_value_eval_from_eval(eval); + B32 ptee_has_content = (direct_type_kind != E_TypeKind_Null && direct_type_kind != E_TypeKind_Void); + B32 ptee_has_string = (E_TypeKind_Char8 <= direct_type_kind && direct_type_kind <= E_TypeKind_UChar32); + DF_Entity *thread = df_entity_from_handle(df_interact_regs()->thread); + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + String8 symbol_name = df_symbol_name_from_process_vaddr(arena, process, value_eval.value.u64, 1); - //- rjf: arrays - case E_TypeKind_Array: + // rjf: special case: push strings for textual string content + B32 did_content = 0; + if(!did_content && ptee_has_string && !has_array && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules)) { - Temp scratch = scratch_begin(&arena, 1); - E_Type *eval_type = e_type_from_key(scratch.arena, eval.type_key); - E_TypeKey direct_type_key = eval_type->direct_type_key; - E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - U64 array_count = eval_type->count; - - // rjf: determine presence of array view rule -> omit c-string fastpath - DF_CfgVal *array_cfg = df_cfg_val_from_string(cfg_table, str8_lit("array")); - B32 has_array = (array_cfg != &df_g_nil_cfg_val); - - // rjf: get pointed-at type - B32 direct_type_is_string = (direct_type_kind != E_TypeKind_Null && - ((E_TypeKind_Char8 <= direct_type_kind && direct_type_kind <= E_TypeKind_UChar32) || - direct_type_kind == E_TypeKind_S8 || - direct_type_kind == E_TypeKind_U8)); - B32 special_case = 0; - - // rjf: special-case: strings - if(!has_array && direct_type_is_string) + did_content = 1; + U64 string_memory_addr = value_eval.value.u64; + U64 element_size = e_type_byte_size_from_key(direct_type_key); + U64 string_buffer_size = 256; + U8 *string_buffer = push_array(arena, U8, string_buffer_size); + for(U64 try_size = string_buffer_size; try_size >= 16; try_size /= 2) { - special_case = 1; - DF_Entity *thread = df_entity_from_handle(df_interact_regs()->thread); - DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); - U64 element_size = e_type_byte_size_from_key(eval_type->direct_type_key); - - // rjf: read text - String8 text_data = {0}; - switch(eval.mode) + B32 read_good = e_space_read(eval.space, string_buffer, r1u64(string_memory_addr, string_memory_addr+try_size)); + if(read_good) { - default:{}break; - case E_Mode_Offset: - { - // TODO(rjf): @spaces pick the right process from the eval's space - CTRL_ProcessMemorySlice text_slice = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, eval.value.u64, 256, element_size, 0); - text_data = text_slice.data; - }break; - case E_Mode_Value: - { - text_data = str8_cstring_capped(&eval.value.u512[0], (U8 *)(&eval.value.u512[0]) + sizeof(eval.value.u512)); - }break; - } - - // rjf: convert to utf-8 if needed - String8 raw_text = {0}; - switch(element_size) - { - default:{raw_text = text_data;}break; - case 2: {raw_text = str8_from_16(arena, str16((U16 *)text_data.str, text_data.size/sizeof(U16)));}break; - case 4: {raw_text = str8_from_32(arena, str32((U32 *)text_data.str, text_data.size/sizeof(U32)));}break; - } - String8 text = df_escaped_from_raw_string(arena, raw_text); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, text).x; - space_taken += 2*f_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("\"")).x; - str8_list_push(arena, &list, str8_lit("\"")); - str8_list_push(arena, &list, text); - str8_list_push(arena, &list, str8_lit("\"")); - } - - // rjf: open brace - if(!special_case) - { - String8 brace = str8_lit("["); - str8_list_push(arena, &list, brace); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, brace).x; - } - - // rjf: content - if(!special_case) - { - if(depth < 3) - { - U64 direct_type_byte_size = e_type_byte_size_from_key(direct_type_key); - for(U64 idx = 0; idx < array_count && max_size > space_taken; idx += 1) - { - E_Eval element_eval = e_element_eval_from_array_eval_index(eval, idx); - String8List element_strs = df_value_strings_from_eval(arena, flags, default_radix, font, font_size, max_size-space_taken, depth+1, element_eval, opt_member, cfg_table); - space_taken += f_dim_from_tag_size_string_list(font, font_size, 0, 0, element_strs).x; - str8_list_concat_in_place(&list, &element_strs); - if(idx+1 < array_count) - { - String8 comma = str8_lit(", "); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, comma).x; - str8_list_push(arena, &list, comma); - } - } - } - else - { - String8 ellipses = str8_lit("..."); - str8_list_push(arena, &list, ellipses); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; + break; } } - - // rjf: close brace - if(!special_case) + string_buffer[string_buffer_size-1] = 0; + String8 string = {0}; + switch(element_size) { - String8 brace = str8_lit("]"); - str8_list_push(arena, &list, brace); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, brace).x; + default:{string = str8_cstring((char *)string_buffer);}break; + case 2: {string = str8_from_16(arena, str16_cstring((U16 *)string_buffer));}break; + case 4: {string = str8_from_32(arena, str32_cstring((U32 *)string_buffer));}break; } - scratch_end(scratch); - }break; + String8 string_escaped = df_escaped_from_raw_string(arena, string); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, string_escaped).x; + space_taken += 2*f_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("\"")).x; + str8_list_push(arena, out, str8_lit("\"")); + str8_list_push(arena, out, string_escaped); + str8_list_push(arena, out, str8_lit("\"")); + } - //- rjf: structs - case E_TypeKind_Struct: - case E_TypeKind_Union: - case E_TypeKind_Class: - case E_TypeKind_IncompleteStruct: - case E_TypeKind_IncompleteUnion: - case E_TypeKind_IncompleteClass: + // rjf: special case: push strings for symbols + if(!did_content && symbol_name.size != 0 && + (type_kind == E_TypeKind_Function || direct_type_kind == E_TypeKind_Function || direct_type_kind == E_TypeKind_Void) && + (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules)) { - // rjf: open brace + did_content = 1; + str8_list_push(arena, out, symbol_name); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, symbol_name).x; + } + + // rjf: descend for all other cases + if(!did_content && ptee_has_content && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules)) + { + did_content = 1; + if(depth<4) { - String8 brace = str8_lit("{"); - str8_list_push(arena, &list, brace); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, brace).x; - } - - // rjf: content - if(depth < 4) - { - Temp scratch = scratch_begin(&arena, 1); - E_MemberArray data_members = e_type_data_members_from_key(scratch.arena, eval.type_key); - E_MemberArray filtered_data_members = df_filtered_data_members_from_members_cfg_table(scratch.arena, data_members, cfg_table); - for(U64 member_idx = 0; member_idx < filtered_data_members.count && max_size > space_taken; member_idx += 1) - { - E_Member *mem = &filtered_data_members.v[member_idx]; - E_Eval member_eval = zero_struct; - member_eval.type_key = mem->type_key; - member_eval.mode = eval.mode; - member_eval.space = eval.space; - member_eval.value = eval.value; - member_eval.value.u64 += mem->off; - String8List member_strs = df_value_strings_from_eval(arena, flags, default_radix, font, font_size, max_size-space_taken, depth+1, member_eval, opt_member, cfg_table); - space_taken += f_dim_from_tag_size_string_list(font, font_size, 0, 0, member_strs).x; - str8_list_concat_in_place(&list, &member_strs); - if(member_idx+1 < filtered_data_members.count) - { - String8 comma = str8_lit(", "); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, comma).x; - str8_list_push(arena, &list, comma); - } - } - scratch_end(scratch); + E_Expr *deref_expr = e_expr_ref_deref(scratch.arena, eval.expr); + E_Eval deref_eval = e_eval_from_expr(scratch.arena, deref_expr); + space_taken += df_append_value_strings_from_eval(arena, flags, radix, font, font_size, max_size-space_taken, depth+1, deref_eval, cfg_table, out); } else { String8 ellipses = str8_lit("..."); - str8_list_push(arena, &list, ellipses); + str8_list_push(arena, out, ellipses); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; + } + } + + // rjf: push pointer value + B32 did_ptr_value = 0; + if((!no_addr || !did_content) && depth == 0) + { + did_ptr_value = 1; + if(did_content) + { + String8 ptr_prefix = str8_lit(" ("); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, ptr_prefix).x; + str8_list_push(arena, out, ptr_prefix); + } + String8 string = df_string_from_simple_typed_eval(arena, flags, radix, value_eval); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, string).x; + str8_list_push(arena, out, string); + if(did_content) + { + String8 close = str8_lit(")"); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, close).x; + str8_list_push(arena, out, close); + } + } + }break; + + //- rjf: arrays + case E_TypeKind_Array: + { + // rjf: unpack type info + E_Type *eval_type = e_type_from_key(scratch.arena, eval.type_key); + E_TypeKey direct_type_key = eval_type->direct_type_key; + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); + U64 array_count = eval_type->count; + + // rjf: get pointed-at type + B32 array_is_string = ((E_TypeKind_Char8 <= direct_type_kind && direct_type_kind <= E_TypeKind_UChar32) || + direct_type_kind == E_TypeKind_S8 || + direct_type_kind == E_TypeKind_U8); + + // rjf: special case: push strings for textual string content + B32 did_content = 0; + if(!did_content && array_is_string && !has_array && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules)) + { + U64 element_size = e_type_byte_size_from_key(direct_type_key); + did_content = 1; + U64 string_buffer_size = 256; + U8 *string_buffer = push_array(arena, U8, string_buffer_size); + switch(eval.mode) + { + case E_Mode_Offset: + { + U64 string_memory_addr = eval.value.u64; + for(U64 try_size = string_buffer_size; try_size >= 16; try_size /= 2) + { + B32 read_good = e_space_read(eval.space, string_buffer, r1u64(string_memory_addr, string_memory_addr+try_size)); + if(read_good) + { + break; + } + } + }break; + case E_Mode_Value: + { + MemoryCopy(string_buffer, &eval.value.u512[0], Min(string_buffer_size, sizeof(eval.value))); + }break; + } + string_buffer[string_buffer_size-1] = 0; + String8 string = {0}; + switch(element_size) + { + default:{string = str8_cstring(string_buffer);}break; + case 2: {string = str8_from_16(arena, str16_cstring((U16 *)string_buffer));}break; + case 4: {string = str8_from_32(arena, str32_cstring((U32 *)string_buffer));}break; + } + String8 string_escaped = df_escaped_from_raw_string(arena, string); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, string_escaped).x; + space_taken += 2*f_dim_from_tag_size_string(font, font_size, 0, 0, str8_lit("\"")).x; + str8_list_push(arena, out, str8_lit("\"")); + str8_list_push(arena, out, string_escaped); + str8_list_push(arena, out, str8_lit("\"")); + } + + // rjf: descend in all other cases + if(!did_content) + { + did_content = 1; + + // rjf: [ + { + String8 bracket = str8_lit("["); + str8_list_push(arena, out, bracket); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, bracket).x; + } + + // rjf: build contents + if(depth < 4) + { + for(U64 idx = 0; idx < array_count && max_size > space_taken; idx += 1) + { + E_Expr *element_expr = e_expr_ref_array_index(scratch.arena, eval.expr, idx); + E_Eval element_eval = e_eval_from_expr(scratch.arena, element_expr); + space_taken += df_append_value_strings_from_eval(arena, flags, radix, font, font_size, max_size-space_taken, depth+1, element_eval, cfg_table, out); + if(idx+1 < array_count) + { + String8 comma = str8_lit(", "); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, comma).x; + str8_list_push(arena, out, comma); + } + } + } + else + { + String8 ellipses = str8_lit("..."); + str8_list_push(arena, out, ellipses); space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; } - // rjf: close brace + // rjf: ] { - String8 brace = str8_lit("}"); - str8_list_push(arena, &list, brace); - space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, brace).x; + String8 bracket = str8_lit("]"); + str8_list_push(arena, out, bracket); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, bracket).x; } - - }break; - } + } + }break; + + //- rjf: structs + case E_TypeKind_Struct: + case E_TypeKind_Union: + case E_TypeKind_Class: + case E_TypeKind_IncompleteStruct: + case E_TypeKind_IncompleteUnion: + case E_TypeKind_IncompleteClass: + { + // rjf: open brace + { + String8 brace = str8_lit("{"); + str8_list_push(arena, out, brace); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, brace).x; + } + + // rjf: content + if(depth < 4) + { + E_MemberArray data_members = e_type_data_members_from_key(scratch.arena, eval.type_key); + E_MemberArray filtered_data_members = df_filtered_data_members_from_members_cfg_table(scratch.arena, data_members, cfg_table); + for(U64 member_idx = 0; member_idx < filtered_data_members.count && max_size > space_taken; member_idx += 1) + { + E_Member *mem = &filtered_data_members.v[member_idx]; + E_Expr *dot_expr = e_expr_ref_member_access(scratch.arena, eval.expr, mem->name); + E_Eval dot_eval = e_eval_from_expr(scratch.arena, dot_expr); + space_taken += df_append_value_strings_from_eval(arena, flags, radix, font, font_size, max_size-space_taken, depth+1, dot_eval, cfg_table, out); + if(member_idx+1 < filtered_data_members.count) + { + String8 comma = str8_lit(", "); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, comma).x; + str8_list_push(arena, out, comma); + } + } + } + else + { + String8 ellipses = str8_lit("..."); + str8_list_push(arena, out, ellipses); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, ellipses).x; + } + + // rjf: close brace + { + String8 brace = str8_lit("}"); + str8_list_push(arena, out, brace); + space_taken += f_dim_from_tag_size_string(font, font_size, 0, 0, brace).x; + } + }break; } + + scratch_end(scratch); ProfEnd(); - return list; + return space_taken; } internal String8 -df_value_string_from_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, E_Eval eval, E_Member *opt_member, DF_CfgTable *cfg_table) +df_value_string_from_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, E_Eval eval, DF_CfgTable *cfg_table) { Temp scratch = scratch_begin(&arena, 1); - String8List parts = df_value_strings_from_eval(scratch.arena, flags, default_radix, font, font_size, max_size, 0, eval, opt_member, cfg_table); - String8 result = str8_list_join(arena, &parts, 0); + String8List strs = {0}; + df_append_value_strings_from_eval(scratch.arena, flags, default_radix, font, font_size, max_size, 0, eval, cfg_table, &strs); + String8 result = str8_list_join(arena, &strs, 0); scratch_end(scratch); return result; } -internal DF_EvalVizWindowedRowList -df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DF_EvalView *eval_view, U32 default_radix, F_Tag font, F32 font_size, Rng1S64 visible_range, DF_EvalVizBlockList *blocks) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(&arena, 1); - - ////////////////////////////// - //- rjf: produce windowed rows, per block - // - U64 visual_idx_off = 0; - U64 semantic_idx_off = 0; - DF_EvalVizWindowedRowList list = {0}; - for(DF_EvalVizBlockNode *n = blocks->first; n != 0; n = n->next) - { - DF_EvalVizBlock *block = &n->v; - - ////////////////////////////// - //- rjf: extract block info - // - U64 block_num_visual_rows = dim_1u64(block->visual_idx_range); - U64 block_num_semantic_rows = dim_1u64(block->semantic_idx_range); - Rng1S64 block_visual_range = r1s64(visual_idx_off, visual_idx_off + block_num_visual_rows); - Rng1S64 block_semantic_range = r1s64(semantic_idx_off, semantic_idx_off + block_num_semantic_rows); - E_TypeKind block_type_kind = e_type_kind_from_key(block->eval.type_key); - - ////////////////////////////// - //- rjf: get skip/chop of block's index range - // - U64 num_skipped_visual = 0; - U64 num_chopped_visual = 0; - { - if(visible_range.min > block_visual_range.min) - { - num_skipped_visual = (visible_range.min - block_visual_range.min); - num_skipped_visual = Min(num_skipped_visual, block_num_visual_rows); - } - if(visible_range.max < block_visual_range.max) - { - num_chopped_visual = (block_visual_range.max - visible_range.max); - num_chopped_visual = Min(num_chopped_visual, block_num_visual_rows); - } - } - - ////////////////////////////// - //- rjf: get visible idx range & invisible counts - // - Rng1U64 visible_idx_range = block->visual_idx_range; - { - visible_idx_range.min += num_skipped_visual; - visible_idx_range.max -= num_chopped_visual; - } - - ////////////////////////////// - //- rjf: sum & advance - // - 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; - } - visual_idx_off += block_num_visual_rows; - semantic_idx_off += block_num_semantic_rows; - - ////////////////////////////// - //- rjf: produce rows, depending on block's kind - // - if(visible_idx_range.max > visible_idx_range.min) switch(block->kind) - { - default:{}break; - - ////////////////////////////// - //- rjf: null -> empty row - // - case DF_EvalVizBlockKind_Null: - { - E_Eval eval = zero_struct; - df_eval_viz_row_list_push_new(arena, eval_view, &list, block, block->key, eval); - }break; - - ////////////////////////////// - //- rjf: root -> just a single row. possibly expandable. - // - case DF_EvalVizBlockKind_Root: - { - DF_EvalVizRow *row = df_eval_viz_row_list_push_new(arena, eval_view, &list, block, block->key, block->eval); - row->display_expr = block->string; - row->edit_expr = block->string; - if(block->member && block->member->kind == E_MemberKind_Padding) - { - row->flags |= DF_EvalVizRowFlag_ExprIsSpecial; - } - }break; - - ////////////////////////////// - //- rjf: members -> produce rows for the visible range of members. - // - case DF_EvalVizBlockKind_Members: - if(block_type_kind != E_TypeKind_Null) - { - E_MemberArray data_members = e_type_data_members_from_key(scratch.arena, block->eval.type_key); - E_MemberArray filtered_data_members = df_filtered_data_members_from_members_cfg_table(scratch.arena, data_members, block->cfg_table); - for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max && idx < filtered_data_members.count; idx += 1) - { - E_Member *member = &filtered_data_members.v[idx]; - - // rjf: get keys for this row - DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(block->parent_key), idx+1); - - // rjf: get member eval - E_Eval member_eval = zero_struct; - { - member_eval.type_key = member->type_key; - member_eval.mode = block->eval.mode; - member_eval.space = block->eval.space; - member_eval.value = block->eval.value; - member_eval.value.u64 += member->off; - } - - // rjf: get view rules - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, key); - DF_CfgTable view_rule_table = df_cfg_table_from_inheritance(scratch.arena, block->cfg_table); - df_cfg_table_push_unparsed_string(scratch.arena, &view_rule_table, view_rule_string, DF_CfgSrc_User); - - // rjf: apply view rules to eval - { - member_eval = e_dynamically_typed_eval_from_eval(member_eval); - member_eval = df_eval_from_eval_cfg_table(arena, member_eval, &view_rule_table); - } - - // rjf: build & push row - DF_EvalVizRow *row = df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, member_eval); - row->member = e_type_member_copy(arena, member); - if(member->kind == E_MemberKind_Padding) - { - row->flags |= DF_EvalVizRowFlag_ExprIsSpecial; - } - row->display_expr = push_str8_copy(arena, member->name); - row->edit_expr = push_str8f(arena, "%S.%S", block->string, member->name); - } - }break; - - ////////////////////////////// - //- rjf: enum members -> produce rows for the visible range of enum members. - // - case DF_EvalVizBlockKind_EnumMembers: - if(block_type_kind == E_TypeKind_Enum) - { - E_Type *type = e_type_from_key(scratch.arena, block->eval.type_key); - for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max && idx < type->count; idx += 1) - { - E_EnumVal *enum_val = &type->enum_vals[idx]; - DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(block->parent_key), idx+1); - - // rjf: produce eval for this enum member - E_Eval eval = zero_struct; - { - eval.type_key = block->eval.type_key; - eval.mode = E_Mode_Value; - eval.space = block->eval.space; - eval.value.u64 = enum_val->val; - } - - // rjf: get view rules - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, key); - DF_CfgTable view_rule_table = df_cfg_table_from_inheritance(scratch.arena, block->cfg_table); - df_cfg_table_push_unparsed_string(scratch.arena, &view_rule_table, view_rule_string, DF_CfgSrc_User); - - // rjf: apply view rules to eval - { - eval = e_dynamically_typed_eval_from_eval(eval); - eval = df_eval_from_eval_cfg_table(arena, eval, &view_rule_table); - } - - // rjf: build & push row - DF_EvalVizRow *row = df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, eval); - row->display_expr = push_str8_copy(arena, enum_val->name); - row->edit_expr = row->display_expr; - } - }break; - - ////////////////////////////// - //- rjf: elements -> produce rows for the visible range of elements. - // - case DF_EvalVizBlockKind_Elements: - { - E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(block->eval.type_key))); - E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - U64 direct_type_key_byte_size = e_type_byte_size_from_key(direct_type_key); - for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1) - { - // rjf: get keys for this row - DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(block->parent_key), idx+1); - - // rjf: get eval for this element - E_Eval elem_eval = e_element_eval_from_array_eval_index(block->eval, idx); - - // rjf: get view rules - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, key); - DF_CfgTable view_rule_table = df_cfg_table_from_inheritance(scratch.arena, block->cfg_table); - df_cfg_table_push_unparsed_string(scratch.arena, &view_rule_table, view_rule_string, DF_CfgSrc_User); - - // rjf: apply view rules to eval - { - elem_eval = e_dynamically_typed_eval_from_eval(elem_eval); - elem_eval = df_eval_from_eval_cfg_table(arena, elem_eval, &view_rule_table); - } - - // rjf: build row - DF_EvalVizRow *row = df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, elem_eval); - row->display_expr = push_str8f(arena, "[%I64u]", idx); - row->edit_expr = push_str8f(arena, "%S[%I64u]", block->string, idx); - } - }break; - - ////////////////////////////// - //- rjf: links -> produce rows for the visible range of links in the linked-list chain. - // - case DF_EvalVizBlockKind_Links: - { - DF_EvalLinkBaseChunkList link_base_chunks = df_eval_link_base_chunk_list_from_eval(scratch.arena, block->link_member_type_key, block->link_member_off, block->eval, 512); - DF_EvalLinkBaseArray link_bases = df_eval_link_base_array_from_chunk_list(scratch.arena, &link_base_chunks); - String8 node_type_string = e_type_string_from_key(arena, block->eval.type_key); - for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1) - { - // rjf: get key for this row - DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(block->parent_key), idx+1); - - // rjf: get link base - DF_EvalLinkBase *link_base = &link_bases.v[idx]; - - // rjf: get eval for this link - E_Eval link_eval = zero_struct; - { - link_eval.type_key = block->eval.type_key; - link_eval.mode = E_Mode_Offset; - link_eval.space = block->eval.space; - link_eval.value.u64= link_base->offset; - } - - // rjf: get view rules - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, key); - DF_CfgTable view_rule_table = df_cfg_table_from_inheritance(scratch.arena, block->cfg_table); - df_cfg_table_push_unparsed_string(scratch.arena, &view_rule_table, view_rule_string, DF_CfgSrc_User); - - // rjf: apply view rules to eval - link_eval = e_dynamically_typed_eval_from_eval(link_eval); - link_eval = df_eval_from_eval_cfg_table(arena, link_eval, &view_rule_table); - E_TypeKind link_type_kind = e_type_kind_from_key(link_eval.type_key); - - // rjf: build row - DF_EvalVizRow *row = df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, link_eval); - row->display_expr = push_str8f(arena, "[%I64u]", idx); - row->edit_expr = push_str8f(arena, "(%S *)0xI64x", node_type_string, link_eval.value.u64); - } - }break; - - ////////////////////////////// - //- rjf: canvas -> produce blank row, sized by the idx range specified in the block - // - case DF_EvalVizBlockKind_Canvas: - if(num_skipped_visual < block_num_visual_rows) - { - DF_ExpandKey key = df_expand_key_make(df_hash_from_expand_key(block->parent_key), 1); - DF_EvalVizRow *row = df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, block->eval); - row->flags = DF_EvalVizRowFlag_Canvas; - row->edit_expr = block->string; - row->size_in_rows = dim_1u64(intersect_1u64(visible_idx_range, r1u64(0, dim_1u64(block->visual_idx_range)))); - row->skipped_size_in_rows= (visible_idx_range.min > block->visual_idx_range.min) ? visible_idx_range.min - block->visual_idx_range.min : 0; - row->chopped_size_in_rows= (visible_idx_range.max < block->visual_idx_range.max) ? block->visual_idx_range.max - visible_idx_range.max : 0; - }break; - - ////////////////////////////// - //- rjf: all elements of a debug info table -> produce rows for visible range - // - case DF_EvalVizBlockKind_DebugInfoTable: - for(U64 idx = visible_idx_range.min; idx < visible_idx_range.max; idx += 1) - { - FZY_Item *item = &block->fzy_backing_items.v[idx]; - - // rjf: determine dbgi/rdi to which this item belongs - RDI_Parsed *rdi = &di_rdi_parsed_nil; - U64 base_idx = 0; - { - for(U64 module_idx = 0; module_idx < e_parse_ctx->modules_count; module_idx += 1) - { - U64 all_items_count = 0; - rdi_section_raw_table_from_kind(e_parse_ctx->modules[module_idx].rdi, block->fzy_target, &all_items_count); - if(base_idx <= item->idx && item->idx < base_idx + all_items_count) - { - rdi = e_parse_ctx->modules[module_idx].rdi; - break; - } - base_idx += all_items_count; - } - } - - // rjf: unpack info about this row - String8 name = fzy_item_string_from_rdi_target_element_idx(rdi, block->fzy_target, block->fzy_backing_items.v[idx].idx - base_idx); - - // rjf: get keys for this row - DF_ExpandKey parent_key = block->parent_key; - DF_ExpandKey key = block->key; - key.child_num = block->fzy_backing_items.v[idx].idx; - - // rjf: get eval for this row - E_Eval eval = e_eval_from_string(arena, name); - - // rjf: get view rules - String8 view_rule_string = df_eval_view_rule_from_key(eval_view, key); - DF_CfgTable view_rule_table = df_cfg_table_from_inheritance(scratch.arena, block->cfg_table); - df_cfg_table_push_unparsed_string(scratch.arena, &view_rule_table, view_rule_string, DF_CfgSrc_User); - - // rjf: apply view rules to eval - { - eval = e_dynamically_typed_eval_from_eval(eval); - eval = df_eval_from_eval_cfg_table(arena, eval, &view_rule_table); - } - - // rjf: build row - DF_EvalVizRow *row = df_eval_viz_row_list_push_new(arena, eval_view, &list, block, key, eval); - row->display_expr = name; - row->edit_expr = name; - }break; - } - } - scratch_end(scratch); - ProfEnd(); - return list; -} - //////////////////////////////// //~ rjf: Hover Eval @@ -11588,8 +11206,7 @@ df_code_slice(DF_Window *ws, DF_CodeSliceParams *params, TxtPt *cursor, TxtPt *m if(!e_type_key_match(e_type_key_zero(), eval.type_key)) { DF_CfgTable cfg_table = {0}; - String8List eval_strings = df_value_strings_from_eval(scratch.arena, DF_EvalVizStringFlag_ReadOnlyDisplayRules, 10, params->font, params->font_size, params->font_size*60.f, 0, eval, 0, &cfg_table); - eval_string = str8_list_join(scratch.arena, &eval_strings, 0); + eval_string = df_value_string_from_eval(scratch.arena, DF_EvalVizStringFlag_ReadOnlyDisplayRules, 10, params->font, params->font_size, params->font_size*60.f, eval, &cfg_table); } ui_spacer(ui_em(1.5f, 1.f)); ui_set_next_pref_width(ui_children_sum(1)); diff --git a/src/df/gfx/df_gfx.h b/src/df/gfx/df_gfx.h index b0f603d9..a7decabe 100644 --- a/src/df/gfx/df_gfx.h +++ b/src/df/gfx/df_gfx.h @@ -323,7 +323,7 @@ enum #define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_NAME(name) df_gfx_view_rule_row_ui__##name #define DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_DEF(name) DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_SIG(DF_GFX_VIEW_RULE_ROW_UI_FUNCTION_NAME(name)) -#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(name) void name(struct DF_Window *ws, DF_ExpandKey key, E_Eval eval, String8 string, struct DF_CfgNode *cfg, Vec2F32 dim) +#define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(name) void name(struct DF_Window *ws, DF_ExpandKey key, E_Eval eval, struct DF_CfgNode *cfg, Vec2F32 dim) #define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_NAME(name) df_gfx_view_rule_block_ui__##name #define DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_DEF(name) DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_SIG(DF_GFX_VIEW_RULE_BLOCK_UI_FUNCTION_NAME(name)) @@ -965,10 +965,8 @@ internal void df_window_update_and_render(Arena *arena, DF_Window *ws, DF_CmdLis //////////////////////////////// //~ rjf: Eval Viz -internal String8 df_escaped_from_raw_string(Arena *arena, String8 raw); -internal String8List df_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, S32 depth, E_Eval eval, E_Member *opt_member, DF_CfgTable *cfg_table); -internal String8 df_value_string_from_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, E_Eval eval, E_Member *opt_member, DF_CfgTable *cfg_table); -internal DF_EvalVizWindowedRowList df_eval_viz_windowed_row_list_from_viz_block_list(Arena *arena, DF_EvalView *eval_view, U32 default_radix, F_Tag font, F32 font_size, Rng1S64 visible_range, DF_EvalVizBlockList *blocks); +internal F32 df_append_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, S32 depth, E_Eval eval, DF_CfgTable *cfg_table, String8List *out); +internal String8 df_value_string_from_eval(Arena *arena, DF_EvalVizStringFlags flags, U32 default_radix, F_Tag font, F32 font_size, F32 max_size, E_Eval eval, DF_CfgTable *cfg_table); //////////////////////////////// //~ rjf: Hover Eval diff --git a/src/df/gfx/df_view_rules.c b/src/df/gfx/df_view_rules.c index c1930ea2..d6cd1711 100644 --- a/src/df/gfx/df_view_rules.c +++ b/src/df/gfx/df_view_rules.c @@ -1,6 +1,173 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +//////////////////////////////// +//~ rjf: "default" + +DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(default) +{ + Temp scratch = scratch_begin(&arena, 1); + + //////////////////////////// + //- rjf: unpack expression type info + // + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, expr); + E_TypeKey type_key = e_type_unwrap(irtree.type_key); + E_TypeKind type_kind = e_type_kind_from_key(type_key); + E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(type_key)); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); + + //////////////////////////// + //- rjf: do struct/union/class member block generation + // + if((type_kind == E_TypeKind_Struct || + type_kind == E_TypeKind_Union || + type_kind == E_TypeKind_Class) || + (e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct || + direct_type_kind == E_TypeKind_Union || + direct_type_kind == E_TypeKind_Class))) + { + // rjf: type -> filtered data members + E_MemberArray data_members = e_type_data_members_from_key(scratch.arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key); + E_MemberArray filtered_data_members = df_filtered_data_members_from_members_cfg_table(arena, data_members, cfg_table); + + // 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); + { + last_vb->expr = expr; + last_vb->cfg_table = cfg_table; + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, filtered_data_members.count); + last_vb->members = filtered_data_members; + } + for(DF_ExpandNode *child = expand_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; + E_Expr *child_expr = df_expr_from_eval_viz_block_index(arena, last_vb, child_idx); + if(child_idx >= last_vb->semantic_idx_range.max) + { + continue; + } + + // rjf: form split: truncate & complete last block; begin next block + last_vb = df_eval_viz_block_split_and_continue(arena, out, last_vb, child_idx); + + // rjf: build child config table + DF_CfgTable *child_cfg_table = cfg_table; + { + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, child->key); + if(view_rule_string.size != 0) + { + child_cfg_table = push_array(arena, DF_CfgTable, 1); + *child_cfg_table = df_cfg_table_from_inheritance(arena, cfg_table); + df_cfg_table_push_unparsed_string(arena, child_cfg_table, view_rule_string, DF_CfgSrc_User); + } + } + + // rjf: recurse for child + df_append_viz_blocks_for_parent__rec(arena, eval_view, key, child->key, str8_zero(), child_expr, child_cfg_table, depth+1, out); + } + df_eval_viz_block_end(out, last_vb); + } + + //////////////////////////// + //- rjf: do enum member block generation + // + // (just a single block for all enum members; enum members can never be expanded) + // + else if(type_kind == E_TypeKind_Enum || + (e_type_kind_is_pointer_or_ref(type_kind) && direct_type_kind == E_TypeKind_Enum)) + { + E_Type *type = e_type_from_key(arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key); + DF_EvalVizBlock *last_vb = df_eval_viz_block_begin(arena, DF_EvalVizBlockKind_EnumMembers, key, df_expand_key_make(df_hash_from_expand_key(key), 0), depth+1); + { + last_vb->expr = expr; + last_vb->cfg_table = cfg_table; + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, type->count); + last_vb->enum_vals.v = type->enum_vals; + last_vb->enum_vals.count = type->count; + } + df_eval_viz_block_end(out, last_vb); + } + + //////////////////////////// + //- rjf: do array element block generation + // + else if(type_kind == E_TypeKind_Array || + (e_type_kind_is_pointer_or_ref(type_kind) && direct_type_kind == E_TypeKind_Array)) + { + // rjf: unpack array type info + E_Type *array_type = e_type_from_key(scratch.arena, e_type_kind_is_pointer_or_ref(type_kind) ? direct_type_key : type_key); + U64 array_count = array_type->count; + + // 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); + { + last_vb->expr = expr; + last_vb->cfg_table = cfg_table; + last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, array_count); + } + for(DF_ExpandNode *child = expand_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; + E_Expr *child_expr = df_expr_from_eval_viz_block_index(arena, last_vb, child_idx); + if(child_idx >= last_vb->semantic_idx_range.max) + { + continue; + } + + // rjf: form split: truncate & complete last block; begin next block + last_vb = df_eval_viz_block_split_and_continue(arena, out, last_vb, child_idx); + + // rjf: build child config table + DF_CfgTable *child_cfg_table = cfg_table; + { + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, child->key); + if(view_rule_string.size != 0) + { + child_cfg_table = push_array(arena, DF_CfgTable, 1); + *child_cfg_table = df_cfg_table_from_inheritance(arena, cfg_table); + df_cfg_table_push_unparsed_string(arena, child_cfg_table, view_rule_string, DF_CfgSrc_User); + } + } + + // rjf: recurse for child + df_append_viz_blocks_for_parent__rec(arena, eval_view, key, child->key, str8_zero(), child_expr, child_cfg_table, depth+1, out); + } + df_eval_viz_block_end(out, last_vb); + } + + //////////////////////////// + //- rjf: do pointer-to-pointer block generation + // + else if(e_type_kind_is_pointer_or_ref(type_kind) && e_type_kind_is_pointer_or_ref(direct_type_kind)) + { + // rjf: compute key + DF_ExpandKey child_key = df_expand_key_make(df_hash_from_expand_key(key), 1); + + // rjf: build child config table + DF_CfgTable *child_cfg_table = cfg_table; + { + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, child_key); + if(view_rule_string.size != 0) + { + child_cfg_table = push_array(arena, DF_CfgTable, 1); + *child_cfg_table = df_cfg_table_from_inheritance(arena, cfg_table); + df_cfg_table_push_unparsed_string(arena, child_cfg_table, view_rule_string, DF_CfgSrc_User); + } + } + + // rjf: recurse for child + E_Expr *child_expr = e_expr_ref_deref(arena, expr); + df_append_viz_blocks_for_parent__rec(arena, eval_view, key, child_key, str8_zero(), child_expr, child_cfg_table, depth+1, out); + } + + scratch_end(scratch); +} + //////////////////////////////// //~ rjf: "array" @@ -322,11 +489,11 @@ df_vr_eval_commit_rgba(E_Eval eval, Vec4F32 rgba) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(rgba) { 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->string = string; - vb->cfg_table = cfg_table; - vb->visual_idx_range = r1u64(0, 8); + vb->string = string; + vb->expr = expr; + vb->visual_idx_range = r1u64(0, 8); vb->semantic_idx_range = r1u64(0, 1); + vb->cfg_table = cfg_table; df_eval_viz_block_end(out, vb); } @@ -505,11 +672,11 @@ df_vr_txt_topology_info_from_cfg(DF_CfgNode *cfg) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(text) { 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->string = string; - vb->cfg_table = cfg_table; - vb->visual_idx_range = r1u64(0, 8); + vb->string = string; + vb->expr = expr; + vb->visual_idx_range = r1u64(0, 8); vb->semantic_idx_range = r1u64(0, 1); + vb->cfg_table = cfg_table; df_eval_viz_block_end(out, vb); } @@ -652,11 +819,11 @@ df_vr_disasm_topology_info_from_cfg(DF_CfgNode *cfg) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(disasm) { 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->string = string; - vb->cfg_table = cfg_table; - vb->visual_idx_range = r1u64(0, 8); + vb->string = string; + vb->expr = expr; + vb->visual_idx_range = r1u64(0, 8); vb->semantic_idx_range = r1u64(0, 1); + vb->cfg_table = cfg_table; df_eval_viz_block_end(out, vb); } @@ -774,11 +941,11 @@ DF_VIEW_UI_FUNCTION_DEF(disasm) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(graph) { 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->string = string; - vb->cfg_table = cfg_table; - vb->visual_idx_range = r1u64(0, 8); + vb->string = string; + vb->expr = expr; + vb->visual_idx_range = r1u64(0, 8); vb->semantic_idx_range = r1u64(0, 1); + vb->cfg_table = cfg_table; df_eval_viz_block_end(out, vb); } @@ -916,11 +1083,11 @@ internal UI_BOX_CUSTOM_DRAW(df_vr_bitmap_box_draw) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(bitmap) { 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->string = string; - vb->cfg_table = cfg_table; - vb->visual_idx_range = r1u64(0, 8); + vb->string = string; + vb->expr = expr; + vb->visual_idx_range = r1u64(0, 8); vb->semantic_idx_range = r1u64(0, 1); + vb->cfg_table = cfg_table; df_eval_viz_block_end(out, vb); } @@ -1326,11 +1493,11 @@ internal UI_BOX_CUSTOM_DRAW(df_vr_geo_box_draw) DF_CORE_VIEW_RULE_VIZ_BLOCK_PROD_FUNCTION_DEF(geo) { 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->string = string; - vb->cfg_table = cfg_table; - vb->visual_idx_range = r1u64(0, 16); + vb->string = string; + vb->expr = expr; + vb->visual_idx_range = r1u64(0, 16); vb->semantic_idx_range = r1u64(0, 1); + vb->cfg_table = cfg_table; df_eval_viz_block_end(out, vb); } diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 8f6ff812..0502a618 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -1232,7 +1232,7 @@ df_string_from_eval_viz_row_column(Arena *arena, DF_EvalView *ev, DF_EvalVizRow default:{}break; case DF_WatchViewColumnKind_Expr: { - result = editable ? row->edit_expr : row->display_expr; + result = df_expr_string_from_viz_row(arena, row); if(row->member != 0 && row->member->inheritance_key_chain.first != 0) { Temp scratch = scratch_begin(&arena, 1); @@ -1255,11 +1255,14 @@ df_string_from_eval_viz_row_column(Arena *arena, DF_EvalView *ev, DF_EvalVizRow }break; case DF_WatchViewColumnKind_Value: { - result = df_value_string_from_eval(arena, !editable * DF_EvalVizStringFlag_ReadOnlyDisplayRules, default_radix, font, font_size, max_size_px, row->eval, row->member, row->cfg_table); + E_Eval eval = e_eval_from_expr(arena, row->expr); + result = df_value_string_from_eval(arena, !editable * DF_EvalVizStringFlag_ReadOnlyDisplayRules, default_radix, font, font_size, max_size_px, eval, row->cfg_table); }break; case DF_WatchViewColumnKind_Type: { - result = !e_type_key_match(row->eval.type_key, e_type_key_zero()) ? e_type_string_from_key(arena, row->eval.type_key) : str8_zero(); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, row->expr); + E_TypeKey type_key = irtree.type_key; + result = !e_type_key_match(type_key, e_type_key_zero()) ? e_type_string_from_key(arena, type_key) : str8_zero(); result = str8_skip_chop_whitespace(result); }break; case DF_WatchViewColumnKind_ViewRule: @@ -1268,14 +1271,16 @@ df_string_from_eval_viz_row_column(Arena *arena, DF_EvalView *ev, DF_EvalVizRow }break; case DF_WatchViewColumnKind_Module: { + E_Eval eval = e_eval_from_expr(arena, row->expr); DF_Entity *process = df_entity_from_handle(df_interact_regs()->process); - DF_Entity *module = df_module_from_process_vaddr(process, row->eval.value.u64); + DF_Entity *module = df_module_from_process_vaddr(process, eval.value.u64); result = df_display_string_from_entity(arena, module); }break; case DF_WatchViewColumnKind_Member: { - E_Eval member_eval = e_member_eval_from_eval_member_name(row->eval, str8(col->string_buffer, col->string_size)); - result = df_value_string_from_eval(arena, !editable * DF_EvalVizStringFlag_ReadOnlyDisplayRules, default_radix, font, font_size, max_size_px, member_eval, row->member, row->cfg_table); + E_Expr *expr = e_expr_ref_member_access(arena, row->expr, str8(col->string_buffer, col->string_size)); + E_Eval eval = e_eval_from_expr(arena, expr); + result = df_value_string_from_eval(arena, !editable * DF_EvalVizStringFlag_ReadOnlyDisplayRules, default_radix, font, font_size, max_size_px, eval, row->cfg_table); }break; } return result; @@ -1467,7 +1472,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS switch(ewv->fill_kind) { //////////////////////////// - //- rjf: mutable watch fill -> build blocks from top-level mutable root expressions + //- rjf: watch fill -> build blocks from top-level watch expressions // default: case DF_WatchViewFillKind_Watch: @@ -1495,7 +1500,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS }break; //////////////////////////// - //- rjf: mutable breakpoint fill -> build blocks from all breakpoints + //- rjf: breakpoint fill -> build blocks from all breakpoints // case DF_WatchViewFillKind_Breakpoints: { @@ -1523,20 +1528,18 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS } E_MemberArray bp_members_array = e_member_array_from_list(scratch.arena, &bp_members); E_TypeKey bp_type = e_type_key_cons(.kind = E_TypeKind_Struct, .name = str8_lit("Breakpoint"), .members = bp_members_array.v, .count = bp_members_array.count); - E_Eval eval = - { - .mode = E_Mode_Offset, - .space = (U64)bp, - .type_key = bp_type, - }; + E_Expr *bp_expr = e_push_expr(scratch.arena, E_ExprKind_LeafID, 0); + bp_expr->type_key = bp_type; + bp_expr->mode = E_Mode_Offset; + bp_expr->space = (U64)bp; DF_CfgTable cfg_table = {0}; - df_append_viz_blocks_for_parent__rec(scratch.arena, eval_view, parent_key, key, title, eval, 0, &cfg_table, 0, &blocks); + df_append_viz_blocks_for_parent__rec(scratch.arena, eval_view, parent_key, key, title, bp_expr, &cfg_table, 0, &blocks); } } }break; //////////////////////////// - //- rjf: mutable watch pin fill -> build blocks from all watch pins + //- rjf: watch pin fill -> build blocks from all watch pins // case DF_WatchViewFillKind_WatchPins: { @@ -1561,14 +1564,12 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS } E_MemberArray wp_members_array = e_member_array_from_list(scratch.arena, &wp_members); E_TypeKey wp_type = e_type_key_cons(.kind = E_TypeKind_Struct, .name = str8_lit("Watch Pin"), .members = wp_members_array.v, .count = wp_members_array.count); - E_Eval eval = - { - .mode = E_Mode_Offset, - .space = (U64)wp, - .type_key = wp_type, - }; + E_Expr *wp_expr = e_push_expr(scratch.arena, E_ExprKind_LeafID, 0); + wp_expr->type_key = wp_type; + wp_expr->mode = E_Mode_Offset; + wp_expr->space = (U64)wp; DF_CfgTable cfg_table = {0}; - df_append_viz_blocks_for_parent__rec(scratch.arena, eval_view, parent_key, key, title, eval, 0, &cfg_table, 0, &blocks); + df_append_viz_blocks_for_parent__rec(scratch.arena, eval_view, parent_key, key, title, wp_expr, &cfg_table, 0, &blocks); } } }break; @@ -1620,26 +1621,26 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS DF_EvalVizBlock *block = df_eval_viz_block_begin(scratch.arena, DF_EvalVizBlockKind_Root, parent_key, key, 0); { E_TypeKey type_key = zero_struct; - String8 name = {0}; if(row->procedure != 0) { type_key = e_type_key_ext(E_TypeKind_Function, row->procedure->type_idx, e_parse_ctx_module_idx_from_rdi(row->rdi)); - name.str = rdi_name_from_procedure(row->rdi, row->procedure, &name.size); } else if(row->inline_site != 0) { type_key = e_type_key_ext(E_TypeKind_Function, row->inline_site->type_idx, e_parse_ctx_module_idx_from_rdi(row->rdi)); - name.str = rdi_string_from_idx(row->rdi, row->inline_site->name_string_idx, &name.size); } - E_Eval eval = - { - .value = {.u64 = regs_rip_from_arch_block(arch, row->regs)}, - .mode = E_Mode_Value, - .space = (U64)process, - .type_key = type_key, - }; - block->eval = eval; - block->string = name; + U64 row_vaddr = regs_rip_from_arch_block(arch, row->regs); + DF_Entity *module = df_module_from_process_vaddr(process, row_vaddr); + U64 row_voff = df_voff_from_vaddr(module, row_vaddr); + E_OpList ops = {0}; + e_oplist_push_op(scratch.arena, &ops, RDI_EvalOp_ModuleOff, row_voff); + String8 bytecode = e_bytecode_from_oplist(scratch.arena, &ops); + E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafBytecode, 0); + expr->bytecode = bytecode; + expr->mode = E_Mode_Value; + expr->space = (U64)process; + expr->type_key = type_key; + block->expr = expr; block->visual_idx_range = r1u64(row_idx, row_idx+1); block->semantic_idx_range = r1u64(row_idx, row_idx+1); } @@ -1806,6 +1807,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS } //- rjf: build blocks for all table items, split by sorted sub-expansions + DF_CfgTable *cfg_table = push_array(scratch.arena, DF_CfgTable, 1); DF_EvalVizBlock *last_vb = df_eval_viz_block_begin(scratch.arena, DF_EvalVizBlockKind_DebugInfoTable, parent_key, root_key, 0); { last_vb->visual_idx_range = last_vb->semantic_idx_range = r1u64(0, items.count); @@ -1815,43 +1817,25 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS for(U64 sub_expand_idx = 0; sub_expand_idx < sub_expand_keys_count; sub_expand_idx += 1) { FZY_Item *item = &items.v[sub_expand_item_idxs[sub_expand_idx]]; + E_Expr *child_expr = df_expr_from_eval_viz_block_index(scratch.arena, last_vb, item->idx); // rjf: form split: truncate & complete last block; begin next block last_vb = df_eval_viz_block_split_and_continue(scratch.arena, &blocks, last_vb, sub_expand_item_idxs[sub_expand_idx]); - // rjf: grab rdi for this item - RDI_Parsed *rdi = &di_rdi_parsed_nil; - U64 base_idx = 0; + // rjf: build child config table + DF_CfgTable *child_cfg_table = cfg_table; { - for(U64 rdi_idx = 0; rdi_idx < rdis_count; rdi_idx += 1) + String8 view_rule_string = df_eval_view_rule_from_key(eval_view, sub_expand_keys[sub_expand_idx]); + if(view_rule_string.size != 0) { - U64 elements_count = 0; - rdi_section_raw_table_from_kind(rdis[rdi_idx], fzy_target, &elements_count); - if(base_idx <= item->idx && item->idx < base_idx + elements_count) - { - rdi = rdis[rdi_idx]; - break; - } - base_idx += elements_count; + child_cfg_table = push_array(scratch.arena, DF_CfgTable, 1); + *child_cfg_table = df_cfg_table_from_inheritance(scratch.arena, cfg_table); + df_cfg_table_push_unparsed_string(scratch.arena, child_cfg_table, view_rule_string, DF_CfgSrc_User); } } - // rjf: grab name for the expanded row - String8 name = fzy_item_string_from_rdi_target_element_idx(rdi, fzy_target, sub_expand_keys[sub_expand_idx].child_num-base_idx); - - // rjf: recurse for sub-expansion - { - 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(scratch.arena, &child_cfg, view_rule_string, DF_CfgSrc_User); - } - } - E_Eval eval = e_eval_from_string(scratch.arena, name); - df_append_viz_blocks_for_parent__rec(scratch.arena, eval_view, parent_key, sub_expand_keys[sub_expand_idx], name, eval, 0, &child_cfg, 0, &blocks); - } + // rjf: recurse for child + df_append_viz_blocks_for_parent__rec(scratch.arena, eval_view, parent_key, sub_expand_keys[sub_expand_idx], str8_zero(), child_expr, child_cfg_table, 0, &blocks); } df_eval_viz_block_end(&blocks, last_vb); }break; @@ -2030,9 +2014,8 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS ewv->text_edit_state_slots_count = u64_up_to_pow2(selection_dim.y+1); ewv->text_edit_state_slots_count = Max(ewv->text_edit_state_slots_count, 64); ewv->text_edit_state_slots = push_array(ewv->text_edit_arena, DF_WatchViewTextEditState*, ewv->text_edit_state_slots_count); - DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, default_radix, code_font, ui_top_font_size(), - r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), - ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks); + DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), + ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks); DF_EvalVizRow *row = rows.first; for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y; y += 1, row = row->next) { @@ -2063,18 +2046,17 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS if(!ewv->text_editing && evt->slot == UI_EventActionSlot_Accept && selection_tbl.min.x <= 0) { taken = 1; - DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, default_radix, code_font, ui_top_font_size(), - r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), - ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks); + DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), + ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks); DF_EvalVizRow *row = rows.first; for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row != 0; y += 1, row = row->next) { - if(row->flags & DF_EvalVizRowFlag_CanExpand) + if(df_viz_row_is_expandable(row)) { B32 is_expanded = df_expand_key_is_set(&eval_view->expand_tree_table, row->key); df_expand_set_expansion(eval_view->arena, &eval_view->expand_tree_table, row->parent_key, row->key, !is_expanded); } - if(row->flags & DF_EvalVizRowFlag_Canvas) + if(row->expand_ui_rule_spec != &df_g_nil_gfx_view_rule_spec && row->expand_ui_rule_spec != 0) { DF_CfgNode *cfg = df_cfg_tree_copy(scratch.arena, row->expand_ui_rule_node); DF_CfgNode *cfg_root = push_array(scratch.arena, DF_CfgNode, 1); @@ -2085,9 +2067,9 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS cfg->parent = cfg_root; } DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); - p.string = row->edit_expr; + p.string = e_string_from_expr(scratch.arena, row->expr); p.view_spec = df_tab_view_spec_from_gfx_view_rule_spec(row->expand_ui_rule_spec); - p.cfg_node = cfg_root; + p.cfg_node = cfg_root; df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_ViewSpec); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_CfgNode); @@ -2105,13 +2087,14 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS selection_tbl.min.x == 1) { taken = 1; - DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, default_radix, code_font, ui_top_font_size(), - r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), - ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks); + DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), + ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks); DF_EvalVizRow *row = rows.first; - if(!(row->flags & DF_EvalVizRowFlag_CanEditValue)) + B32 row_is_editable = df_viz_row_is_editable(row); + if(!row_is_editable) { - U64 vaddr = row->eval.value.u64; + E_Eval eval = e_eval_from_expr(scratch.arena, row->expr); + U64 vaddr = eval.value.u64; DF_Entity *module = df_module_from_process_vaddr(process, vaddr); DI_Key dbgi_key = df_dbgi_key_from_module(module); U64 voff = df_voff_from_vaddr(module, vaddr); @@ -2231,14 +2214,14 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS case DF_WatchViewColumnKind_Value: if(editing_complete && evt->slot != UI_EventActionSlot_Cancel) { - DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, default_radix, code_font, ui_top_font_size(), - r1s64(ui_scroll_list_row_from_item(&row_blocks, y-1), - ui_scroll_list_row_from_item(&row_blocks, y-1)+1), &blocks); + DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, r1s64(ui_scroll_list_row_from_item(&row_blocks, y-1), + ui_scroll_list_row_from_item(&row_blocks, y-1)+1), &blocks); B32 success = 0; if(rows.first != 0) { - E_Eval write_eval = e_eval_from_string(scratch.arena, new_string); - success = df_commit_eval_value(rows.first->eval, write_eval); + E_Eval dst_eval = e_eval_from_expr(scratch.arena, rows.first->expr); + E_Eval src_eval = e_eval_from_string(scratch.arena, new_string); + success = df_commit_eval_value(dst_eval, src_eval); } if(!success) { @@ -2292,9 +2275,8 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS { taken = 1; String8List strs = {0}; - DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, default_radix, code_font, ui_top_font_size(), - r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), - ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks); + DF_EvalVizWindowedRowList rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, r1s64(ui_scroll_list_row_from_item(&row_blocks, selection_tbl.min.y-1), + ui_scroll_list_row_from_item(&row_blocks, selection_tbl.max.y-1)+1), &blocks); DF_EvalVizRow *row = rows.first; for(S64 y = selection_tbl.min.y; y <= selection_tbl.max.y && row != 0; y += 1, row = row->next) { @@ -2649,7 +2631,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS // DF_EvalVizWindowedRowList rows = {0}; { - rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, default_radix, code_font, ui_top_font_size(), r1s64(visible_row_rng.min-1, visible_row_rng.max), &blocks); + rows = df_eval_viz_windowed_row_list_from_viz_block_list(scratch.arena, eval_view, r1s64(visible_row_rng.min-1, visible_row_rng.max), &blocks); } //////////////////////////// @@ -2666,6 +2648,9 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS U64 row_hash = df_hash_from_expand_key(row->key); B32 row_selected = (selection_tbl.min.y <= (semantic_idx+1) && (semantic_idx+1) <= selection_tbl.max.y); B32 row_expanded = df_expand_key_is_set(&eval_view->expand_tree_table, row->key); + E_Eval row_eval = e_eval_from_expr(scratch.arena, row->expr); + B32 row_is_expandable = df_viz_row_is_expandable(row); + B32 row_is_editable = df_viz_row_is_editable(row); B32 next_row_expanded = row_expanded; //////////////////////// @@ -2673,25 +2658,29 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS // B32 row_is_fresh = 0; B32 row_is_bad = 0; - switch(row->eval.mode) + switch(row_eval.mode) { default:{}break; case E_Mode_Offset: + if(row_eval.space >= E_Space_FIXED_COUNT) { - // TODO(rjf): @spaces pick the right process from the eval's space - U64 size = e_type_byte_size_from_key(row->eval.type_key); - size = Min(size, 64); - Rng1U64 vaddr_rng = r1u64(row->eval.value.u64, row->eval.value.u64+size); - CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, vaddr_rng, 0); - for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1) + DF_Entity *space_entity = (DF_Entity *)row_eval.space; + if(space_entity->kind == DF_EntityKind_Process) { - if(slice.byte_changed_flags[idx] != 0) + U64 size = e_type_byte_size_from_key(row_eval.type_key); + size = Min(size, 64); + Rng1U64 vaddr_rng = r1u64(row_eval.value.u64, row_eval.value.u64+size); + CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, space_entity->ctrl_machine_id, space_entity->ctrl_handle, vaddr_rng, 0); + for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1) { - row_is_fresh = 1; - } - if(slice.byte_bad_flags[idx] != 0) - { - row_is_bad = 1; + if(slice.byte_changed_flags[idx] != 0) + { + row_is_fresh = 1; + } + if(slice.byte_bad_flags[idx] != 0) + { + row_is_bad = 1; + } } } }break; @@ -2718,14 +2707,15 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS ui_set_next_pref_width(ui_pct(1, 0)); ui_set_next_pref_height(ui_px(scroll_list_params.row_height_px*row->size_in_rows, 1.f)); ui_set_next_focus_hot(row_selected ? UI_FocusKind_On : UI_FocusKind_Off); - UI_Box *row_box = ui_build_box_from_stringf(row_flags|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_Clickable|(!(row->flags & DF_EvalVizRowFlag_Canvas) * UI_BoxFlag_DisableFocusOverlay), "row_%I64x", row_hash); + UI_Box *row_box = ui_build_box_from_stringf(row_flags|UI_BoxFlag_DrawSideBottom|UI_BoxFlag_Clickable|((row->expand_ui_rule_spec == &df_g_nil_gfx_view_rule_spec) * UI_BoxFlag_DisableFocusOverlay), "row_%I64x", row_hash); ui_ts_vector_idx += 1; ui_ts_cell_idx = 0; //////////////////////// - //- rjf: canvas row -> fill with canvas ui build + //- rjf: row with expand ui rule -> build large singular row for "escape hatch" ui // - if(row->flags & DF_EvalVizRowFlag_Canvas) UI_Parent(row_box) UI_FocusHot(row_selected ? UI_FocusKind_On : UI_FocusKind_Off) + if(row->expand_ui_rule_spec != &df_g_nil_gfx_view_rule_spec) + UI_Parent(row_box) UI_FocusHot(row_selected ? UI_FocusKind_On : UI_FocusKind_Off) { //- rjf: build canvas row contents ui_set_next_fixed_y(-1.f * (row->skipped_size_in_rows) * scroll_list_params.row_height_px); @@ -2738,7 +2728,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS { Vec2F32 canvas_dim = v2f32(scroll_list_params.dim_px.x - ui_top_font_size()*1.5f, (row->skipped_size_in_rows+row->size_in_rows+row->chopped_size_in_rows)*scroll_list_params.row_height_px); - row->expand_ui_rule_spec->info.block_ui(ws, row->key, row->eval, row->edit_expr, row->expand_ui_rule_node, canvas_dim); + row->expand_ui_rule_spec->info.block_ui(ws, row->key, row_eval, row->expand_ui_rule_node, canvas_dim); } } @@ -2766,9 +2756,9 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS cfg->parent = cfg_root; } DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); - p.string = row->edit_expr; + p.string = e_string_from_expr(scratch.arena, row->expr); p.view_spec = df_tab_view_spec_from_gfx_view_rule_spec(row->expand_ui_rule_spec); - p.cfg_node = cfg_root; + p.cfg_node = cfg_root; df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_ViewSpec); df_cmd_params_mark_slot(&p, DF_CmdParamSlot_CfgNode); @@ -2780,14 +2770,14 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS //////////////////////// //- rjf: build non-canvas row contents // - if(!(row->flags & DF_EvalVizRowFlag_Canvas)) UI_Parent(row_box) UI_HeightFill + if(row->expand_ui_rule_spec == &df_g_nil_gfx_view_rule_spec) UI_Parent(row_box) UI_HeightFill { ////////////////////// //- rjf: draw start of cache lines in expansions // - if((row->eval.mode == E_Mode_Offset || row->eval.mode == E_Mode_Null) && - row->eval.msgs.count == 0 && - row->eval.value.u64%64 == 0 && row->depth > 0 && + if((row_eval.mode == E_Mode_Offset || row_eval.mode == E_Mode_Null) && + row_eval.msgs.count == 0 && + row_eval.value.u64%64 == 0 && row->depth > 0 && !row_expanded) { ui_set_next_fixed_x(0); @@ -2800,14 +2790,14 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS ////////////////////// //- rjf: draw mid-row cache line boundaries in expansions // - if((row->eval.mode == E_Mode_Offset || row->eval.mode == E_Mode_Null) && - row->eval.msgs.max_kind == E_MsgKind_Null && - row->eval.value.u64%64 != 0 && + if((row_eval.mode == E_Mode_Offset || row_eval.mode == E_Mode_Null) && + row_eval.msgs.max_kind == E_MsgKind_Null && + row_eval.value.u64%64 != 0 && row->depth > 0 && !row_expanded) { - U64 next_off = (row->eval.value.u64 + e_type_byte_size_from_key(row->eval.type_key)); - if(next_off%64 != 0 && row->eval.value.u64/64 < next_off/64) + U64 next_off = (row_eval.value.u64 + e_type_byte_size_from_key(row_eval.type_key)); + if(next_off%64 != 0 && row_eval.value.u64/64 < next_off/64) { ui_set_next_fixed_x(0); ui_set_next_fixed_y(scroll_list_params.row_height_px - ui_top_font_size()*0.5f); @@ -2832,7 +2822,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS String8 cell_pre_edit_string = df_string_from_eval_viz_row_column(scratch.arena, eval_view, row, col, 0, default_radix, ui_top_font(), ui_top_font_size(), row_string_max_size_px); //- rjf: unpack column-kind-specific info - E_Eval cell_eval = row->eval; + E_Eval cell_eval = row_eval; B32 cell_can_edit = 0; FuzzyMatchRangeList cell_matches = {0}; String8 cell_error_string = {0}; @@ -2849,7 +2839,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS cell_can_edit = (row->depth == 0 && modifiable); if(filter.size != 0) { - cell_matches = fuzzy_match_find(scratch.arena, filter, row->display_expr); + cell_matches = fuzzy_match_find(scratch.arena, filter, df_expr_string_from_viz_row(scratch.arena, row)); } cell_autocomp_flags = DF_AutoCompListerFlag_Locals; }break; @@ -2967,10 +2957,10 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS else { sig = df_line_editf(ws, - (DF_LineEditFlag_CodeContents*(!(row->flags & DF_EvalVizRowFlag_ExprIsSpecial) || col->kind != DF_WatchViewColumnKind_Expr)| + (DF_LineEditFlag_CodeContents| DF_LineEditFlag_NoBackground| DF_LineEditFlag_DisableEdit*(!cell_can_edit)| - DF_LineEditFlag_Expander*!!(x == 0 && row->flags & DF_EvalVizRowFlag_CanExpand && col->kind == DF_WatchViewColumnKind_Expr)| + DF_LineEditFlag_Expander*!!(x == 0 && row_is_expandable && col->kind == DF_WatchViewColumnKind_Expr)| DF_LineEditFlag_ExpanderPlaceholder*(x == 0 && row->depth==0 && col->kind == DF_WatchViewColumnKind_Expr)| DF_LineEditFlag_ExpanderSpace*(x == 0 && row->depth!=0 && col->kind == DF_WatchViewColumnKind_Expr)), x == 0 ? row->depth : 0, @@ -3055,7 +3045,7 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS if(DEV_eval_compiler_tooltips && x == 0 && ui_hovering(sig)) UI_Tooltip DF_Font(ws, DF_FontSlot_Code) { local_persist char *spaces = " "; - String8 string = row->display_expr; + String8 string = df_expr_string_from_viz_row(scratch.arena, row); E_TokenArray tokens = e_token_array_from_text(scratch.arena, string); E_Parse parse = e_parse_expr_from_text_tokens(scratch.arena, string, &tokens); E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, parse.expr); @@ -3205,440 +3195,6 @@ df_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_WatchViewS { df_expand_set_expansion(eval_view->arena, &eval_view->expand_tree_table, row->parent_key, row->key, next_row_expanded); } - -#if 0 - //////////////////// - //- rjf: expression - // - ProfScope("expr") - { - DF_WatchViewPoint pt = {DF_WatchViewColumnKind_Expr, row->parent_key, row->key}; - DF_WatchViewTextEditState *edit_state = df_watch_view_text_edit_state_from_pt(ewv, pt); - B32 cell_selected = (row_selected && selection_tbl.min.x <= pt.column_kind && pt.column_kind <= selection_tbl.max.x); - B32 can_edit_expr = !(row->depth > 0 || modifiable == 0); - - // rjf: build - UI_Signal sig = {0}; - B32 next_expanded = row_expanded; - UI_Palette(palette) UI_TableCell - UI_FocusHot(cell_selected ? UI_FocusKind_On : UI_FocusKind_Off) - UI_FocusActive((cell_selected && ewv->text_editing) ? UI_FocusKind_On : UI_FocusKind_Off) - { - B32 expr_editing_active = ui_is_focus_active(); - B32 is_inherited = (row->inherited_type_key_chain.count != 0); - DF_Font(ws, DF_FontSlot_Code) UI_FlagsAdd(row->depth > 0 ? UI_BoxFlag_DrawTextWeak : 0) - { - FuzzyMatchRangeList matches = {0}; - if(filter.size != 0) - { - matches = fuzzy_match_find(scratch.arena, filter, row->display_expr); - } - sig = df_line_editf(ws, - (DF_LineEditFlag_CodeContents*(!(row->flags & DF_EvalVizRowFlag_ExprIsSpecial))| - DF_LineEditFlag_NoBackground*(!is_inherited)| - DF_LineEditFlag_DisableEdit*(!can_edit_expr)| - DF_LineEditFlag_Expander*!!(row->flags & DF_EvalVizRowFlag_CanExpand)| - DF_LineEditFlag_ExpanderPlaceholder*(row->depth==0)| - DF_LineEditFlag_ExpanderSpace*(row->depth!=0)), - row->depth, - filter.size ? &matches : 0, - &edit_state->cursor, &edit_state->mark, edit_state->input_buffer, sizeof(edit_state->input_buffer), &edit_state->input_size, &next_expanded, - row->display_expr, - "###row_%I64x", row_hash); - } - if(is_inherited && ui_hovering(sig)) UI_Tooltip - { - String8List inheritance_chain_type_names = {0}; - for(E_TypeKeyNode *n = row->inherited_type_key_chain.first; n != 0; n = n->next) - { - String8 inherited_type_name = e_type_string_from_key(scratch.arena, n->v); - inherited_type_name = str8_skip_chop_whitespace(inherited_type_name); - str8_list_push(scratch.arena, &inheritance_chain_type_names, inherited_type_name); - } - StringJoin join = {0}; - join.sep = str8_lit("::"); - String8 inheritance_type = str8_list_join(scratch.arena, &inheritance_chain_type_names, &join); - ui_set_next_pref_width(ui_children_sum(1)); - UI_Row - { - ui_labelf("Inherited from "); - DF_Font(ws, DF_FontSlot_Code) df_code_label(1.f, 1.f, df_rgba_from_theme_color(DF_ThemeColor_CodeType), inheritance_type); - } - } - - // rjf: autocomplete lister - if(expr_editing_active && - selection_tbl.min.x == selection_tbl.max.x && selection_tbl.min.y == selection_tbl.max.y && - txt_pt_match(edit_state->cursor, edit_state->mark)) - { - String8 input = str8(edit_state->input_buffer, edit_state->input_size); - DF_AutoCompListerParams params = {DF_AutoCompListerFlag_Locals}; - df_set_autocomp_lister_query(ws, sig.box->key, ¶ms, input, edit_state->cursor.column-1); - } - } - - // rjf: press -> commit if editing & select - if(ui_pressed(sig)) - { - ewv->next_cursor = ewv->next_mark = pt; - pressed = 1; - } - - // rjf: double-click -> start editing - if(ui_double_clicked(sig) && can_edit_expr) - { - ui_kill_action(); - DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); - df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Edit)); - } - - // rjf: [DEV] hovering -> tooltips - if(DEV_eval_compiler_tooltips && ui_hovering(sig)) UI_Tooltip DF_Font(ws, DF_FontSlot_Code) - { - local_persist char *spaces = " "; - String8 string = row->display_expr; - E_TokenArray tokens = e_token_array_from_text(scratch.arena, string); - E_Parse parse = e_parse_expr_from_text_tokens(scratch.arena, string, &tokens); - E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, parse.expr); - E_OpList oplist = e_oplist_from_irtree(scratch.arena, irtree.root); - String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); - UI_Flags(UI_BoxFlag_DrawTextWeak) ui_labelf("Text:"); - ui_label(string); - ui_spacer(ui_em(2.f, 1.f)); - UI_Flags(UI_BoxFlag_DrawTextWeak) ui_labelf("Tokens:"); - for(U64 idx = 0; idx < tokens.count; idx += 1) - { - ui_labelf("%S: '%S'", e_token_kind_strings[tokens.v[idx].kind], str8_substr(string, tokens.v[idx].range)); - } - ui_spacer(ui_em(2.f, 1.f)); - UI_Flags(UI_BoxFlag_DrawTextWeak) ui_labelf("Expression:"); - { - typedef struct Task Task; - struct Task - { - Task *next; - Task *prev; - E_Expr *expr; - S64 depth; - }; - Task start_task = {0, 0, parse.expr}; - Task *first_task = &start_task; - Task *last_task = first_task; - for(Task *t = first_task; t != 0; t = t->next) - { - String8 ext = {0}; - switch(t->expr->kind) - { - default: - { - if(t->expr->string.size != 0) - { - ext = push_str8f(scratch.arena, "'%S'", t->expr->string); - } - else if(t->expr->u32 != 0) - { - ext = push_str8f(scratch.arena, "0x%x", t->expr->u32); - } - else if(t->expr->f32 != 0) - { - ext = push_str8f(scratch.arena, "%f", t->expr->f32); - } - else if(t->expr->f64 != 0) - { - ext = push_str8f(scratch.arena, "%f", t->expr->f64); - } - else if(t->expr->u64 != 0) - { - ext = push_str8f(scratch.arena, "0x%I64x", t->expr->u64); - } - }break; - } - ui_labelf("%.*s%S%s%S", (int)t->depth*2, spaces, e_expr_kind_strings[t->expr->kind], ext.size ? " " : "", ext); - for(E_Expr *child = t->expr->first; child != &e_expr_nil; child = child->next) - { - Task *task = push_array(scratch.arena, Task, 1); - task->expr = child; - task->depth = t->depth+1; - DLLInsert(first_task, last_task, t, task); - } - } - } - ui_spacer(ui_em(2.f, 1.f)); - UI_Flags(UI_BoxFlag_DrawTextWeak) ui_labelf("IR Tree:"); - { - typedef struct Task Task; - struct Task - { - Task *next; - Task *prev; - E_IRNode *node; - S64 depth; - }; - Task start_task = {0, 0, irtree.root}; - Task *first_task = &start_task; - Task *last_task = first_task; - for(Task *t = first_task; t != 0; t = t->next) - { - String8 op_string = {0}; - switch(t->node->op) - { - default:{}break; - case E_IRExtKind_Bytecode:{op_string = str8_lit("Bytecode");}break; - case E_IRExtKind_SetSpace:{op_string = str8_lit("SetSpace");}break; -#define X(name) case RDI_EvalOp_##name:{op_string = str8_lit(#name);}break; - RDI_EvalOp_XList -#undef X - } - String8 ext = {0}; - ui_labelf("%.*s%S", (int)t->depth*2, spaces, op_string); - for(E_IRNode *child = t->node->first; child != &e_irnode_nil; child = child->next) - { - Task *task = push_array(scratch.arena, Task, 1); - task->node = child; - task->depth = t->depth+1; - DLLInsert(first_task, last_task, t, task); - } - } - } - ui_spacer(ui_em(2.f, 1.f)); - UI_Flags(UI_BoxFlag_DrawTextWeak) ui_labelf("Op List:"); - { - for(E_Op *op = oplist.first; op != 0; op = op->next) - { - String8 op_string = {0}; - switch(op->opcode) - { - default:{}break; - case E_IRExtKind_Bytecode:{op_string = str8_lit("Bytecode");}break; - case E_IRExtKind_SetSpace:{op_string = str8_lit("SetSpace");}break; -#define X(name) case RDI_EvalOp_##name:{op_string = str8_lit(#name);}break; - RDI_EvalOp_XList -#undef X - } - String8 ext = {0}; - switch(op->opcode) - { - case E_IRExtKind_Bytecode:{ext = str8_lit("[bytecode]");}break; - default: - { - ext = str8_from_u64(scratch.arena, op->u64, 16, 0, 0); - }break; - } - ui_labelf(" %S%s%S", op_string, ext.size ? " " : "", ext); - } - } - ui_spacer(ui_em(2.f, 1.f)); - UI_Flags(UI_BoxFlag_DrawTextWeak) ui_labelf("Bytecode:"); - { - for(U64 idx = 0; idx < bytecode.size; idx += 1) - { - ui_labelf(" 0x%x ('%c')", (U32)bytecode.str[idx], (char)bytecode.str[idx]); - } - } - } - - // rjf: commit expansion state - if(next_expanded != row_expanded) - { - df_expand_set_expansion(eval_view->arena, &eval_view->expand_tree_table, row->parent_key, row->key, next_expanded); - } - } - - //////////////////// - //- rjf: value - // - ProfScope("value") - { - DF_WatchViewPoint pt = {DF_WatchViewColumnKind_Value, row->parent_key, row->key}; - DF_WatchViewTextEditState *edit_state = df_watch_view_text_edit_state_from_pt(ewv, pt); - B32 cell_selected = (row_selected && selection_tbl.min.x <= pt.column_kind && pt.column_kind <= selection_tbl.max.x); - B32 value_is_error = (row->eval.msgs.max_kind != E_MsgKind_Null); - 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)); - - // rjf: unpack palette - UI_BoxFlags cell_flags = 0; - UI_Palette *palette = ui_top_palette(); - { - if(row_is_bad || value_is_error) - { - palette = ui_build_palette(ui_top_palette(), .text = df_rgba_from_theme_color(DF_ThemeColor_TextNegative), .text_weak = df_rgba_from_theme_color(DF_ThemeColor_TextNegative), .background = df_rgba_from_theme_color(DF_ThemeColor_HighlightOverlayError)); - cell_flags |= UI_BoxFlag_DrawBackground; - } - } - - // rjf: build - UI_Signal sig = {0}; - ui_set_next_flags(cell_flags); - UI_Palette(palette) UI_TableCell DF_Font(ws, DF_FontSlot_Code) - UI_FocusHot(cell_selected ? UI_FocusKind_On : UI_FocusKind_Off) - UI_FocusActive((cell_selected && ewv->text_editing) ? UI_FocusKind_On : UI_FocusKind_Off) - { - // rjf: errors? -> show errors - if(value_is_error) DF_Font(ws, DF_FontSlot_Main) - { - String8List strings = {0}; - for(E_Msg *msg = row->eval.msgs.first; msg != 0; msg = msg->next) - { - str8_list_push(scratch.arena, &strings, msg->text); - } - StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")}; - String8 error_string = str8_list_join(scratch.arena, &strings, &join); - sig = df_error_label(error_string); - } - - // rjf: hook -> call hook - if(value_is_hook) DF_Font(ws, DF_FontSlot_Main) - { - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "###val_%I64x", row_hash); - UI_Parent(box) - { - row->value_ui_rule_spec->info.row_ui(ws, row->key, row->eval, row->value_ui_rule_node); - } - sig = ui_signal_from_box(box); - } - - // rjf: complex values - if(value_is_complex) - { - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "###val_%I64x", row_hash); - UI_Parent(box) - { - df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeDefault), row->display_value); - } - sig = ui_signal_from_box(box); - } - - // rjf: simple values (editable) - if(value_is_simple) UI_TextRasterFlags(df_raster_flags_from_slot(ws, DF_FontSlot_Code)) - { - sig = df_line_editf(ws, DF_LineEditFlag_CodeContents|DF_LineEditFlag_NoBackground, 0, 0, &edit_state->cursor, &edit_state->mark, edit_state->input_buffer, sizeof(edit_state->input_buffer), &edit_state->input_size, 0, row->display_value, "%S###val_%I64x", row->display_value, row_hash); - } - } - - // rjf: bad & hovering -> display - if(row_is_bad && ui_hovering(sig)) UI_Tooltip - { - UI_PrefWidth(ui_children_sum(1)) df_error_label(str8_lit("Could not read memory successfully.")); - } - - // rjf: press -> focus & commit if editing & not selected - if(ui_pressed(sig)) - { - ewv->next_cursor = ewv->next_mark = pt; - pressed = 1; - } - - // rjf: double-click -> start editing - if(ui_double_clicked(sig) && value_is_simple) - { - ui_kill_action(); - DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); - df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Edit)); - } - - // rjf: double-click, not editable -> go-to-location - if(ui_double_clicked(sig) && !(row->flags & DF_EvalVizRowFlag_CanEditValue)) - { - U64 vaddr = row->eval.value.u64; - DF_Entity *module = df_module_from_process_vaddr(process, vaddr); - DI_Key dbgi_key = df_dbgi_key_from_module(module); - U64 voff = df_voff_from_vaddr(module, vaddr); - DF_LineList lines = df_lines_from_dbgi_key_voff(scratch.arena, &dbgi_key, voff); - DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); - p.entity = df_handle_from_entity(process); - p.vaddr = vaddr; - if(lines.first != 0) - { - p.file_path = lines.first->v.file_path; - p.text_point = lines.first->v.pt; - } - df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_FindCodeLocation)); - } - } - - //////////////////// - //- rjf: type - // - ProfScope("type") - { - DF_WatchViewPoint pt = {DF_WatchViewColumnKind_Type, row->parent_key, row->key}; - DF_WatchViewTextEditState *edit_state = df_watch_view_text_edit_state_from_pt(ewv, pt); - B32 cell_selected = (row_selected && selection_tbl.min.x <= pt.column_kind && pt.column_kind <= selection_tbl.max.x); - UI_TableCell DF_Font(ws, DF_FontSlot_Code) - UI_FocusHot(cell_selected ? UI_FocusKind_On : UI_FocusKind_Off) - UI_FocusActive((cell_selected && ewv->text_editing) ? UI_FocusKind_On : UI_FocusKind_Off) - { - E_TypeKey key = row->eval.type_key; - String8 string = e_type_string_from_key(scratch.arena, key); - string = str8_skip_chop_whitespace(string); - UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "###type_%I64x", row_hash); - if(!e_type_key_match(key, e_type_key_zero())) UI_Parent(box) - { - df_code_label(1.f, 1, df_rgba_from_theme_color(DF_ThemeColor_CodeType), string); - } - UI_Signal sig = ui_signal_from_box(box); - if(ui_pressed(sig)) - { - ewv->next_cursor = ewv->next_mark = pt; - pressed = 1; - } - } - } - - //////////////////// - //- rjf: view rule - // - ProfScope("view rule") - { - DF_WatchViewPoint pt = {DF_WatchViewColumnKind_ViewRule, row->parent_key, row->key}; - DF_WatchViewTextEditState *edit_state = df_watch_view_text_edit_state_from_pt(ewv, pt); - B32 cell_selected = (row_selected && selection_tbl.min.x <= pt.column_kind && pt.column_kind <= selection_tbl.max.x); - String8 view_rule = df_eval_view_rule_from_key(eval_view, row->key); - - // rjf: build - UI_Signal sig = {0}; - B32 rule_editing_active = 0; - UI_TableCell DF_Font(ws, DF_FontSlot_Code) - UI_FocusHot(cell_selected ? UI_FocusKind_On : UI_FocusKind_Off) - UI_FocusActive((cell_selected && ewv->text_editing) ? UI_FocusKind_On : UI_FocusKind_Off) - UI_TextRasterFlags(df_raster_flags_from_slot(ws, DF_FontSlot_Code)) - { - rule_editing_active = ui_is_focus_active(); - sig = df_line_editf(ws, DF_LineEditFlag_CodeContents|DF_LineEditFlag_NoBackground, 0, 0, &edit_state->cursor, &edit_state->mark, edit_state->input_buffer, sizeof(edit_state->input_buffer), &edit_state->input_size, 0, view_rule, "###view_rule_%I64x", row_hash); - } - - // rjf: press -> commit if not selected, select this cell - if(ui_pressed(sig)) - { - ewv->next_cursor = ewv->next_mark = pt; - pressed = 1; - } - - // rjf: autocomplete lister - if(rule_editing_active && - selection_tbl.min.x == selection_tbl.max.x && selection_tbl.min.y == selection_tbl.max.y && - txt_pt_match(edit_state->cursor, edit_state->mark)) - { - String8 input = str8(edit_state->input_buffer, edit_state->input_size); - DF_AutoCompListerParams params = df_view_rule_autocomp_lister_params_from_input_cursor(scratch.arena, input, edit_state->cursor.column-1); - if(params.flags == 0) - { - params.flags = DF_AutoCompListerFlag_ViewRules; - } - df_set_autocomp_lister_query(ws, sig.box->key, ¶ms, input, edit_state->cursor.column-1); - } - - // rjf: double-click -> begin editing - if(ui_double_clicked(sig) && !ewv->text_editing) - { - ui_kill_action(); - DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); - df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_Edit)); - } - } -#endif } } } diff --git a/src/eval/eval.mdesk b/src/eval/eval.mdesk index 28156b85..f2738e7e 100644 --- a/src/eval/eval.mdesk +++ b/src/eval/eval.mdesk @@ -73,59 +73,60 @@ E_TypeKindTable: {Variadic "" 0 } } -@table(name op_string) +@table(name op_kind precedence string op_pre op_sep op_pos) E_ExprKindTable: { - { Nil "" } + { Nil Null 0 "" "" "" "" } + { Ref Null 0 "" "" "" "" } - { ArrayIndex "[]" } - { MemberAccess "." } - { Deref "*" } - { Address "&" } + { ArrayIndex Null 0 "[]" "" "[" "]"} + { MemberAccess Null 0 "." "" "." "" } + { Deref UnaryPrefix 2 "*" "*" "" "" } + { Address UnaryPrefix 2 "&" "&" "" "" } - { Cast "cast" } - { Sizeof "sizeof" } + { Cast Null 0 "cast" "" "" "" } + { Sizeof UnaryPrefix 0 "sizeof" "sizeof" "" "" } - { Neg "-" } - { LogNot "!" } - { BitNot "~" } - { Mul "*" } - { Div "/" } - { Mod "%" } - { Add "+" } - { Sub "-" } - { LShift "<<" } - { RShift ">>" } - { Less "<" } - { LsEq "<=" } - { Grtr ">" } - { GrEq ">=" } - { EqEq "==" } - { NtEq "!=" } + { Neg UnaryPrefix 2 "-" "-" "" "" } + { LogNot UnaryPrefix 2 "!" "!" "" "" } + { BitNot UnaryPrefix 2 "~" "~" "" "" } + { Mul Binary 3 "*" "" "*" "" } + { Div Binary 3 "/" "" "/" "" } + { Mod Binary 3 "%" "" "%" "" } + { Add Binary 4 "+" "" "+" "" } + { Sub Binary 4 "-" "" "-" "" } + { LShift Binary 5 "<<" "" "<<" "" } + { RShift Binary 5 ">>" "" ">>" "" } + { Less Binary 6 "<" "" "<" "" } + { LsEq Binary 6 "<=" "" "<=" "" } + { Grtr Binary 6 ">" "" ">" "" } + { GrEq Binary 6 ">=" "" ">=" "" } + { EqEq Binary 7 "==" "" "==" "" } + { NtEq Binary 7 "!=" "" "!=" "" } - { BitAnd "&" } - { BitXor "^" } - { BitOr "|" } - { LogAnd "&&" } - { LogOr "||" } + { BitAnd Binary 8 "&" "" "&" "" } + { BitXor Binary 9 "^" "" "^" "" } + { BitOr Binary 10 "|" "" "|" "" } + { LogAnd Binary 11 "&&" "" "&&" "" } + { LogOr Binary 12 "||" "" "||" "" } - { Ternary "? " } + { Ternary Null 0 "? " "" "?" ":" } - { LeafBytecode "bytecode" } - { LeafMember "member" } - { LeafStringLiteral "string_literal" } - { LeafU64 "U64" } - { LeafF64 "F64" } - { LeafF32 "F32" } - { LeafIdent "leaf_ident" } - { LeafID "leaf_id" } + { LeafBytecode Null 0 "bytecode" "" "" "" } + { LeafMember Null 0 "member" "" "" "" } + { LeafStringLiteral Null 0 "string_literal" "" "" "" } + { LeafU64 Null 0 "U64" "" "" "" } + { LeafF64 Null 0 "F64" "" "" "" } + { LeafF32 Null 0 "F32" "" "" "" } + { LeafIdent Null 0 "leaf_ident" "" "" "" } + { LeafID Null 0 "leaf_id" "" "" "" } - { TypeIdent "type_ident" } - { Ptr "ptr" } - { Array "array" } - { Func "function" } + { TypeIdent Null 0 "type_ident" "" "" "" } + { Ptr Null 0 "ptr" "" "" "" } + { Array Null 0 "array" "" "" "" } + { Func Null 0 "function" "" "" "" } - { Define "=" } + { Define Binary 13 "=" "" "=" "" } } @table(name display_string) @@ -195,9 +196,9 @@ e_expr_kind_strings: @expand(E_InterpretationCodeTable a) `str8_lit_comp("$(a.display_string)")` } -@data(String8) e_expr_op_strings: +@data(E_OpInfo) e_expr_kind_op_info_table: { - @expand(E_ExprKindTable a) `str8_lit_comp("$(a.op_string)")` + @expand(E_ExprKindTable a) `{ E_OpKind_$(a.op_kind), $(a.precedence), str8_lit_comp("$(a.op_pre)"), str8_lit_comp("$(a.op_sep)"), str8_lit_comp("$(a.op_post)") }` } @data(U8) e_kind_basic_byte_size_table: diff --git a/src/eval/eval_bundles.c b/src/eval/eval_bundles.c index e3dc4172..a68a88a2 100644 --- a/src/eval/eval_bundles.c +++ b/src/eval/eval_bundles.c @@ -5,11 +5,9 @@ //~ rjf: Bundled Evaluation Functions internal E_Eval -e_eval_from_string(Arena *arena, String8 string) +e_eval_from_expr(Arena *arena, E_Expr *expr) { - E_TokenArray tokens = e_token_array_from_text(arena, string); - E_Parse parse = e_parse_expr_from_text_tokens(arena, string, &tokens); - E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, parse.expr); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr); E_OpList oplist = e_oplist_from_irtree(arena, irtree.root); String8 bytecode = e_bytecode_from_oplist(arena, &oplist); E_Interpretation interp = e_interpret(bytecode); @@ -18,11 +16,10 @@ e_eval_from_string(Arena *arena, String8 string) .value = interp.value, .mode = irtree.mode, .space = irtree.space, + .expr = expr, .type_key = irtree.type_key, .code = interp.code, - .advance = parse.last_token >= tokens.v + tokens.count ? string.size : parse.last_token->range.min, }; - e_msg_list_concat_in_place(&eval.msgs, &parse.msgs); e_msg_list_concat_in_place(&eval.msgs, &irtree.msgs); if(E_InterpretationCode_Good < eval.code && eval.code < E_InterpretationCode_COUNT) { @@ -31,6 +28,16 @@ e_eval_from_string(Arena *arena, String8 string) return eval; } +internal E_Eval +e_eval_from_string(Arena *arena, String8 string) +{ + E_TokenArray tokens = e_token_array_from_text(arena, string); + E_Parse parse = e_parse_expr_from_text_tokens(arena, string, &tokens); + E_Eval eval = e_eval_from_expr(arena, parse.expr); + e_msg_list_concat_in_place(&eval.msgs, &parse.msgs); + return eval; +} + internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval) { diff --git a/src/eval/eval_bundles.h b/src/eval/eval_bundles.h index e41ab677..957ff123 100644 --- a/src/eval/eval_bundles.h +++ b/src/eval/eval_bundles.h @@ -13,15 +13,16 @@ struct E_Eval E_Value value; E_Mode mode; E_Space space; + E_Expr *expr; E_TypeKey type_key; E_InterpretationCode code; E_MsgList msgs; - U64 advance; }; //////////////////////////////// //~ rjf: Bundled Evaluation Functions +internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr); internal E_Eval e_eval_from_string(Arena *arena, String8 string); internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval); internal E_Eval e_dynamically_typed_eval_from_eval(E_Eval eval); diff --git a/src/eval/eval_core.h b/src/eval/eval_core.h index a32fb8ec..25b67c27 100644 --- a/src/eval/eval_core.h +++ b/src/eval/eval_core.h @@ -36,6 +36,27 @@ struct E_MsgList U64 count; }; +//////////////////////////////// +//~ rjf: Operator Info + +typedef enum E_OpKind +{ + E_OpKind_Null, + E_OpKind_UnaryPrefix, + E_OpKind_Binary, +} +E_OpKind; + +typedef struct E_OpInfo E_OpInfo; +struct E_OpInfo +{ + E_OpKind kind; + S64 precedence; + String8 pre; + String8 sep; + String8 post; +}; + //////////////////////////////// //~ rjf: Evaluation Spaces diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index fa6418da..0cc6311d 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -387,6 +387,12 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr) { default:{}break; + //- rjf: references -> just descend to sub-expr + case E_ExprKind_Ref: + { + result = e_irtree_and_type_from_expr(arena, expr->ref); + }break; + //- rjf: array indices case E_ExprKind_ArrayIndex: { @@ -1093,7 +1099,7 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr) //- rjf: leaf bytecode case E_ExprKind_LeafBytecode: { - E_IRNode *new_tree = e_irtree_bytecode_no_copy(arena, expr->string); + E_IRNode *new_tree = e_irtree_bytecode_no_copy(arena, expr->bytecode); E_TypeKey final_type_key = expr->type_key; result.root = new_tree; result.type_key = final_type_key; diff --git a/src/eval/eval_parse.c b/src/eval/eval_parse.c index f71556a2..0d5e1a92 100644 --- a/src/eval/eval_parse.c +++ b/src/eval/eval_parse.c @@ -17,40 +17,6 @@ global read_only String8 e_multichar_symbol_strings[] = str8_lit_comp("||"), }; -global read_only struct {E_ExprKind kind; String8 string; S64 precedence;} e_unary_prefix_op_table[] = -{ - // { E_ExprKind_???, str8_lit_comp("+"), 2 }, - { E_ExprKind_Neg, str8_lit_comp("-"), 2 }, - { E_ExprKind_LogNot, str8_lit_comp("!"), 2 }, - { E_ExprKind_Deref, str8_lit_comp("*"), 2 }, - { E_ExprKind_Address,str8_lit_comp("&"), 2 }, - { E_ExprKind_Sizeof, str8_lit_comp("sizeof"), 2 }, - // { E_ExprKind_Alignof, str8_lit_comp("_Alignof"), 2 }, -}; - -global read_only struct {E_ExprKind kind; String8 string; S64 precedence;} e_binary_op_table[] = -{ - { E_ExprKind_Mul, str8_lit_comp("*"), 3 }, - { E_ExprKind_Div, str8_lit_comp("/"), 3 }, - { E_ExprKind_Mod, str8_lit_comp("%"), 3 }, - { E_ExprKind_Add, str8_lit_comp("+"), 4 }, - { E_ExprKind_Sub, str8_lit_comp("-"), 4 }, - { E_ExprKind_LShift, str8_lit_comp("<<"), 5 }, - { E_ExprKind_RShift, str8_lit_comp(">>"), 5 }, - { E_ExprKind_Less, str8_lit_comp("<"), 6 }, - { E_ExprKind_LsEq, str8_lit_comp("<="), 6 }, - { E_ExprKind_Grtr, str8_lit_comp(">"), 6 }, - { E_ExprKind_GrEq, str8_lit_comp(">="), 6 }, - { E_ExprKind_EqEq, str8_lit_comp("=="), 7 }, - { E_ExprKind_NtEq, str8_lit_comp("!="), 7 }, - { E_ExprKind_BitAnd, str8_lit_comp("&"), 8 }, - { E_ExprKind_BitXor, str8_lit_comp("^"), 9 }, - { E_ExprKind_BitOr, str8_lit_comp("|"), 10 }, - { E_ExprKind_LogAnd, str8_lit_comp("&&"), 11 }, - { E_ExprKind_LogOr, str8_lit_comp("||"), 12 }, - { E_ExprKind_Define, str8_lit_comp("="), 13 }, -}; - global read_only S64 e_max_precedence = 15; //////////////////////////////// @@ -676,7 +642,7 @@ internal E_Expr * e_push_expr(Arena *arena, E_ExprKind kind, void *location) { E_Expr *e = push_array(arena, E_Expr, 1); - e->first = e->last = e->next = &e_expr_nil; + e->first = e->last = e->next = e->ref = &e_expr_nil; e->location = location; e->kind = kind; return e; @@ -688,6 +654,124 @@ e_expr_push_child(E_Expr *parent, E_Expr *child) SLLQueuePush_NZ(&e_expr_nil, parent->first, parent->last, child, next); } +internal E_Expr * +e_expr_ref(Arena *arena, E_Expr *ref) +{ + E_Expr *expr = e_push_expr(arena, E_ExprKind_Ref, 0); + expr->ref = ref; + return expr; +} + +internal E_Expr * +e_expr_ref_member_access(Arena *arena, E_Expr *lhs, String8 member_name) +{ + E_Expr *root = e_push_expr(arena, E_ExprKind_MemberAccess, 0); + E_Expr *lhs_ref = e_expr_ref(arena, lhs); + E_Expr *rhs = e_push_expr(arena, E_ExprKind_LeafMember, 0); + rhs->string = push_str8_copy(arena, member_name); + e_expr_push_child(root, lhs_ref); + e_expr_push_child(root, rhs); + return root; +} + +internal E_Expr * +e_expr_ref_array_index(Arena *arena, E_Expr *lhs, U64 index) +{ + E_Expr *root = e_push_expr(arena, E_ExprKind_ArrayIndex, 0); + E_Expr *lhs_ref = e_expr_ref(arena, lhs); + E_Expr *rhs = e_push_expr(arena, E_ExprKind_LeafU64, 0); + rhs->u64 = index; + e_expr_push_child(root, lhs_ref); + e_expr_push_child(root, rhs); + return root; +} + +internal E_Expr * +e_expr_ref_deref(Arena *arena, E_Expr *rhs) +{ + E_Expr *root = e_push_expr(arena, E_ExprKind_Deref, 0); + E_Expr *rhs_ref = e_expr_ref(arena, rhs); + e_expr_push_child(root, rhs_ref); + return rhs_ref; +} + +//////////////////////////////// +//~ rjf: Expression Tree -> String Conversions + +internal void +e_append_strings_from_expr(Arena *arena, E_Expr *expr, String8List *out) +{ + switch(expr->kind) + { + default: + { + E_OpInfo *op_info = &e_expr_kind_op_info_table[expr->kind]; + String8 seps[] = + { + op_info->pre, + op_info->sep, + op_info->post, + }; + U64 idx = 0; + for(E_Expr *child = expr->first; child != &e_expr_nil; child = child->next, idx += 1) + { + if(seps[idx].size != 0) + { + str8_list_push(arena, out, seps[idx]); + } + E_OpInfo *child_op_info = &e_expr_kind_op_info_table[child->kind]; + B32 need_parens = (child_op_info->precedence > op_info->precedence); + if(need_parens) + { + str8_list_pushf(arena, out, "("); + } + e_append_strings_from_expr(arena, child, out); + if(need_parens) + { + str8_list_pushf(arena, out, ")"); + } + } + }break; + case E_ExprKind_LeafBytecode: + case E_ExprKind_LeafMember: + case E_ExprKind_LeafIdent: + { + str8_list_push(arena, out, expr->string); + }break; + case E_ExprKind_LeafStringLiteral: + { + str8_list_pushf(arena, out, "\"%S\"", expr->string); + }break; + case E_ExprKind_LeafU64: + case E_ExprKind_LeafID: + { + str8_list_pushf(arena, out, "0x%I64x", expr->u64); + }break; + case E_ExprKind_LeafF64: + { + str8_list_pushf(arena, out, "%f", expr->f64); + }break; + case E_ExprKind_LeafF32: + { + str8_list_pushf(arena, out, "%f", expr->f32); + }break; + case E_ExprKind_TypeIdent: + { + String8 type_string = e_type_string_from_key(arena, expr->type_key); + str8_list_push(arena, out, type_string); + }break; + } +} + +internal String8 +e_string_from_expr(Arena *arena, E_Expr *expr) +{ + String8List strings = {0}; + e_append_strings_from_expr(arena, expr, &strings); + String8 result = str8_list_join(arena, &strings, 0); + return result; +} + //////////////////////////////// //~ rjf: Parsing Functions @@ -966,12 +1050,13 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to void *location = 0; // rjf: try op table - for(U64 idx = 0; idx < ArrayCount(e_unary_prefix_op_table); idx += 1) + for(EachNonZeroEnumVal(E_ExprKind, k)) { - if(str8_match(token_string, e_unary_prefix_op_table[idx].string, 0)) + E_OpInfo *op_info = &e_expr_kind_op_info_table[k]; + if(op_info->kind == E_OpKind_UnaryPrefix && str8_match(op_info->pre, token_string, 0)) { - prefix_unary_precedence = e_unary_prefix_op_table[idx].precedence; - prefix_unary_kind = e_unary_prefix_op_table[idx].kind; + prefix_unary_precedence = op_info->precedence; + prefix_unary_kind = k; break; } } @@ -1445,7 +1530,8 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to atom->mode = E_Mode_Offset; atom->space = space; atom->type_key = type_key; - atom->string = e_bytecode_from_oplist(arena, &oplist); + atom->string = token_string; + atom->bytecode = e_bytecode_from_oplist(arena, &oplist); } else if(alias_code != 0) { @@ -1457,7 +1543,8 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to atom->mode = E_Mode_Offset; atom->space = space; atom->type_key = type_key; - atom->string = e_bytecode_from_oplist(arena, &oplist); + atom->string = token_string; + atom->bytecode = e_bytecode_from_oplist(arena, &oplist); } else { @@ -1470,7 +1557,8 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to atom->mode = E_Mode_Offset; atom->space = space; atom->type_key = type_key; - atom->string = loc_bytecode; + atom->string = token_string; + atom->bytecode = loc_bytecode; }break; case RDI_LocationKind_ValBytecodeStream: { @@ -1478,7 +1566,8 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to atom->mode = E_Mode_Value; atom->space = space; atom->type_key = type_key; - atom->string = loc_bytecode; + atom->string = token_string; + atom->bytecode = loc_bytecode; }break; case RDI_LocationKind_AddrRegPlusU16: { @@ -1492,7 +1581,8 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to atom->mode = E_Mode_Offset; atom->space = space; atom->type_key = type_key; - atom->string = e_bytecode_from_oplist(arena, &oplist); + atom->string = token_string; + atom->bytecode = e_bytecode_from_oplist(arena, &oplist); }break; case RDI_LocationKind_AddrAddrRegPlusU16: { @@ -1507,7 +1597,8 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to atom->mode = E_Mode_Offset; atom->space = space; atom->type_key = type_key; - atom->string = e_bytecode_from_oplist(arena, &oplist); + atom->string = token_string; + atom->bytecode = e_bytecode_from_oplist(arena, &oplist); }break; case RDI_LocationKind_ValReg: { @@ -1522,7 +1613,8 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to atom->mode = E_Mode_Value; atom->space = space; atom->type_key = type_key; - atom->string = e_bytecode_from_oplist(arena, &oplist); + atom->string = token_string; + atom->bytecode = e_bytecode_from_oplist(arena, &oplist); }break; } @@ -1763,12 +1855,13 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to // rjf: first try to find a matching binary operator S64 binary_precedence = 0; E_ExprKind binary_kind = 0; - for(U64 idx = 0; idx < ArrayCount(e_binary_op_table); idx += 1) + for(EachNonZeroEnumVal(E_ExprKind, k)) { - if(str8_match(token_string, e_binary_op_table[idx].string, 0)) + E_OpInfo *op_info = &e_expr_kind_op_info_table[k]; + if(op_info->kind == E_OpKind_Binary && str8_match(op_info->sep, token_string, 0)) { - binary_precedence = e_binary_op_table[idx].precedence; - binary_kind = e_binary_op_table[idx].kind; + binary_precedence = op_info->precedence; + binary_kind = k; break; } } diff --git a/src/eval/eval_parse.h b/src/eval/eval_parse.h index d9dfdddc..d7641e60 100644 --- a/src/eval/eval_parse.h +++ b/src/eval/eval_parse.h @@ -53,6 +53,7 @@ struct E_Expr E_Expr *first; E_Expr *last; E_Expr *next; + E_Expr *ref; void *location; E_ExprKind kind; E_Mode mode; @@ -63,6 +64,7 @@ struct E_Expr U64 u64; F64 f64; String8 string; + String8 bytecode; }; //////////////////////////////// @@ -219,6 +221,17 @@ internal U32 e_parse_ctx_module_idx_from_rdi(RDI_Parsed *rdi); internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, void *location); internal void e_expr_push_child(E_Expr *parent, E_Expr *child); +internal E_Expr *e_expr_ref(Arena *arena, E_Expr *ref); +internal E_Expr *e_expr_ref_member_access(Arena *arena, E_Expr *lhs, String8 member_name); +internal E_Expr *e_expr_ref_array_index(Arena *arena, E_Expr *lhs, U64 index); +internal E_Expr *e_expr_ref_deref(Arena *arena, E_Expr *rhs); + +//////////////////////////////// +//~ rjf: Expression Tree -> String Conversions + +internal void e_append_strings_from_expr(Arena *arena, E_Expr *expr, String8List *out); +internal String8 e_string_from_expr(Arena *arena, E_Expr *expr); + //////////////////////////////// //~ rjf: Parsing Functions diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index 789ed72e..3a6a745d 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -156,6 +156,13 @@ e_type_kind_is_basic_or_enum(E_TypeKind kind) return result; } +internal B32 +e_type_kind_is_pointer_or_ref(E_TypeKind kind) +{ + B32 result = (kind == E_TypeKind_Ptr || kind == E_TypeKind_LRef || kind == E_TypeKind_RRef); + return result; +} + //////////////////////////////// //~ rjf: Member Functions @@ -1409,6 +1416,22 @@ e_type_data_members_from_key(Arena *arena, E_TypeKey key) return members; } +internal E_Member * +e_type_member_from_array_name(E_MemberArray *members, String8 name) +{ + E_Member *member = 0; + for(U64 idx = 0; idx < members->count; idx += 1) + { + if(members->v[idx].kind == E_MemberKind_DataField && + str8_match(members->v[idx].name, name, 0)) + { + member = &members->v[idx]; + break; + } + } + return member; +} + internal void e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec, B32 skip_return) { diff --git a/src/eval/eval_types.h b/src/eval/eval_types.h index 99d8985d..a3b95300 100644 --- a/src/eval/eval_types.h +++ b/src/eval/eval_types.h @@ -210,6 +210,7 @@ internal RDI_EvalTypeGroup e_type_group_from_kind(E_TypeKind kind); internal B32 e_type_kind_is_integer(E_TypeKind kind); internal B32 e_type_kind_is_signed(E_TypeKind kind); internal B32 e_type_kind_is_basic_or_enum(E_TypeKind kind); +internal B32 e_type_kind_is_pointer_or_ref(E_TypeKind kind); //////////////////////////////// //~ rjf: Member Functions @@ -261,6 +262,7 @@ internal B32 e_type_match(E_TypeKey l, E_TypeKey r); internal E_Member *e_type_member_copy(Arena *arena, E_Member *src); internal int e_type_qsort_compare_members_offset(E_Member *a, E_Member *b); internal E_MemberArray e_type_data_members_from_key(Arena *arena, E_TypeKey key); +internal E_Member *e_type_member_from_array_name(E_MemberArray *members, String8 name); internal void e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec, B32 skip_return); internal void e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec); internal String8 e_type_string_from_key(Arena *arena, E_TypeKey key); diff --git a/src/eval/generated/eval.meta.c b/src/eval/generated/eval.meta.c index 5d4411bc..1729ba84 100644 --- a/src/eval/generated/eval.meta.c +++ b/src/eval/generated/eval.meta.c @@ -14,9 +14,10 @@ str8_lit_comp("CharLiteral"), str8_lit_comp("Symbol"), }; -String8 e_expr_kind_strings[42] = +String8 e_expr_kind_strings[43] = { str8_lit_comp("Nil"), +str8_lit_comp("Ref"), str8_lit_comp("ArrayIndex"), str8_lit_comp("MemberAccess"), str8_lit_comp("Deref"), @@ -75,50 +76,51 @@ str8_lit_comp("Insufficient evaluation machine stack space."), str8_lit_comp("Malformed bytecode."), }; -String8 e_expr_op_strings[42] = +E_OpInfo e_expr_kind_op_info_table[43] = { -str8_lit_comp(""), -str8_lit_comp("[]"), -str8_lit_comp("."), -str8_lit_comp("*"), -str8_lit_comp("&"), -str8_lit_comp("cast"), -str8_lit_comp("sizeof"), -str8_lit_comp("-"), -str8_lit_comp("!"), -str8_lit_comp("~"), -str8_lit_comp("*"), -str8_lit_comp("/"), -str8_lit_comp("%"), -str8_lit_comp("+"), -str8_lit_comp("-"), -str8_lit_comp("<<"), -str8_lit_comp(">>"), -str8_lit_comp("<"), -str8_lit_comp("<="), -str8_lit_comp(">"), -str8_lit_comp(">="), -str8_lit_comp("=="), -str8_lit_comp("!="), -str8_lit_comp("&"), -str8_lit_comp("^"), -str8_lit_comp("|"), -str8_lit_comp("&&"), -str8_lit_comp("||"), -str8_lit_comp("? "), -str8_lit_comp("bytecode"), -str8_lit_comp("member"), -str8_lit_comp("string_literal"), -str8_lit_comp("U64"), -str8_lit_comp("F64"), -str8_lit_comp("F32"), -str8_lit_comp("leaf_ident"), -str8_lit_comp("leaf_id"), -str8_lit_comp("type_ident"), -str8_lit_comp("ptr"), -str8_lit_comp("array"), -str8_lit_comp("function"), -str8_lit_comp("="), +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("Nil") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("Ref") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("ArrayIndex") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp("MemberAccess") }, +{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("*"), str8_lit_comp(""), str8_lit_comp("Deref") }, +{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("&"), str8_lit_comp(""), str8_lit_comp("Address") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("Cast") }, +{ E_OpKind_UnaryPrefix, 0, str8_lit_comp("sizeof"), str8_lit_comp(""), str8_lit_comp("Sizeof") }, +{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("-"), str8_lit_comp(""), str8_lit_comp("Neg") }, +{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("!"), str8_lit_comp(""), str8_lit_comp("LogNot") }, +{ E_OpKind_UnaryPrefix, 2, str8_lit_comp("~"), str8_lit_comp(""), str8_lit_comp("BitNot") }, +{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("*"), str8_lit_comp("Mul") }, +{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("/"), str8_lit_comp("Div") }, +{ E_OpKind_Binary, 3, str8_lit_comp(""), str8_lit_comp("%"), str8_lit_comp("Mod") }, +{ E_OpKind_Binary, 4, str8_lit_comp(""), str8_lit_comp("+"), str8_lit_comp("Add") }, +{ E_OpKind_Binary, 4, str8_lit_comp(""), str8_lit_comp("-"), str8_lit_comp("Sub") }, +{ E_OpKind_Binary, 5, str8_lit_comp(""), str8_lit_comp("<<"), str8_lit_comp("LShift") }, +{ E_OpKind_Binary, 5, str8_lit_comp(""), str8_lit_comp(">>"), str8_lit_comp("RShift") }, +{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp("<"), str8_lit_comp("Less") }, +{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp("<="), str8_lit_comp("LsEq") }, +{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(">"), str8_lit_comp("Grtr") }, +{ E_OpKind_Binary, 6, str8_lit_comp(""), str8_lit_comp(">="), str8_lit_comp("GrEq") }, +{ E_OpKind_Binary, 7, str8_lit_comp(""), str8_lit_comp("=="), str8_lit_comp("EqEq") }, +{ E_OpKind_Binary, 7, str8_lit_comp(""), str8_lit_comp("!="), str8_lit_comp("NtEq") }, +{ E_OpKind_Binary, 8, str8_lit_comp(""), str8_lit_comp("&"), str8_lit_comp("BitAnd") }, +{ E_OpKind_Binary, 9, str8_lit_comp(""), str8_lit_comp("^"), str8_lit_comp("BitXor") }, +{ E_OpKind_Binary, 10, str8_lit_comp(""), str8_lit_comp("|"), str8_lit_comp("BitOr") }, +{ E_OpKind_Binary, 11, str8_lit_comp(""), str8_lit_comp("&&"), str8_lit_comp("LogAnd") }, +{ E_OpKind_Binary, 12, str8_lit_comp(""), str8_lit_comp("||"), str8_lit_comp("LogOr") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("?"), str8_lit_comp("Ternary") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("LeafBytecode") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("LeafMember") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("LeafStringLiteral") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("LeafU64") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("LeafF64") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("LeafF32") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("LeafIdent") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("LeafID") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("TypeIdent") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("Ptr") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("Array") }, +{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("Func") }, +{ E_OpKind_Binary, 13, str8_lit_comp(""), str8_lit_comp("="), str8_lit_comp("Define") }, }; U8 e_kind_basic_byte_size_table[55] = diff --git a/src/eval/generated/eval.meta.h b/src/eval/generated/eval.meta.h index 15ddb132..26ea67fc 100644 --- a/src/eval/generated/eval.meta.h +++ b/src/eval/generated/eval.meta.h @@ -91,6 +91,7 @@ typedef U32 E_ExprKind; typedef enum E_ExprKindEnum { E_ExprKind_Nil, +E_ExprKind_Ref, E_ExprKind_ArrayIndex, E_ExprKind_MemberAccess, E_ExprKind_Deref, @@ -153,9 +154,9 @@ E_InterpretationCode_COUNT, C_LINKAGE_BEGIN extern String8 e_token_kind_strings[6]; -extern String8 e_expr_kind_strings[42]; +extern String8 e_expr_kind_strings[43]; extern String8 e_interpretation_code_display_strings[11]; -extern String8 e_expr_op_strings[42]; +extern E_OpInfo e_expr_kind_op_info_table[43]; extern U8 e_kind_basic_byte_size_table[55]; extern String8 e_kind_basic_string_table[55]; diff --git a/src/raddbg/raddbg.h b/src/raddbg/raddbg.h index 96bb2b97..843fc4df 100644 --- a/src/raddbg/raddbg.h +++ b/src/raddbg/raddbg.h @@ -5,6 +5,7 @@ //~ rjf: Frontend/UI Pass Tasks // // [x] fix HRESULTs +// [ ] fix escape char literals // // [ ] fix selecting hover eval, then hover eval disappearing, causing // busted focus, until a new hover eval is opened