From c7a3a73b63d235a6adb2a6513d9d7bcfafb8e86b Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Wed, 9 Apr 2025 17:29:59 -0700 Subject: [PATCH] fix incorrect story for chained lens calls; fix possibly-overridden usage of lens calls in ui build --- src/base/base_strings.c | 1 - src/eval/eval_ir.c | 65 +++---- src/eval/eval_parse.c | 31 ++-- .../eval_visualization_core.c | 170 +++++++++--------- src/raddbg/raddbg_views.c | 11 +- 5 files changed, 134 insertions(+), 144 deletions(-) diff --git a/src/base/base_strings.c b/src/base/base_strings.c index e8b620dc..47b94f74 100644 --- a/src/base/base_strings.c +++ b/src/base/base_strings.c @@ -1970,7 +1970,6 @@ escaped_from_raw_str8(Arena *arena, String8 string) 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) { diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 56e83ce2..7cbf0dfc 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -1514,47 +1514,8 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) { default:{}break; - //- rjf: member accesses + //- rjf: member accesses & array indexing expressions case E_ExprKind_MemberAccess: - { - // rjf: unpack left-hand-size - E_Expr *lhs = expr->first; - E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); - - // rjf: if the right-hand-side is a call, then this is short-hand for - // the right-hand-side call, with the left-hand-side as the first argument. - E_Expr *rhs = lhs->next; - if(rhs->kind == E_ExprKind_Call) - { - E_Expr *rhs_copy = e_expr_copy(arena, rhs); - e_expr_insert_child(rhs_copy, rhs_copy->first, e_expr_ref(arena, lhs)); - result = e_irtree_and_type_from_expr(arena, rhs_copy); - } - - // rjf: if the right-hand-side is a leaf identifier, then this is an - // "access" to the left-hand-side. - else if(rhs->kind == E_ExprKind_LeafIdentifier) - { - // rjf: pick access hook based on type - E_Type *lhs_type = e_type_from_key__cached(lhs_irtree.type_key); - E_TypeAccessFunctionType *lhs_access = lhs_type->access; - if(lhs_access == 0) - { - lhs_access = E_TYPE_ACCESS_FUNCTION_NAME(default); - } - - // rjf: call into hook to do access - result = lhs_access(arena, expr, &lhs_irtree); - } - - // rjf: if the right-hand-side is anything else, this is an invalid formation. - else - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Expected identifier or call after `.`."); - } - }break; - - //- rjf: array indices case E_ExprKind_ArrayIndex: { // rjf: unpack left-hand-size @@ -2171,9 +2132,29 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) E_TypeKey lhs_type_key = lhs_irtree.type_key; E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); + // rjf: calling an unresolved leaf-identifier member access, and we can determine + // that that identifer maps to a type? -> generate a call expression with the + // left-hand-side of the dot operator as the first argument. this is a fast path + // which prevents paren nesting in simple cases, to easily chain multiple + // calls - for example, bin(2).digits(4) + if(lhs_type == &e_type_nil && + lhs->kind == E_ExprKind_MemberAccess) + { + E_Expr *callee = lhs->first->next; + E_Expr *first_arg = e_expr_ref(arena, lhs->first); + E_Expr *call = e_push_expr(arena, E_ExprKind_Call, 0); + e_expr_push_child(call, callee); + e_expr_push_child(call, first_arg); + for(E_Expr *arg = lhs->next; arg != &e_expr_nil; arg = arg->next) + { + e_expr_push_child(call, e_expr_ref(arena, arg)); + } + result = e_irtree_and_type_from_expr(arena, call); + } + // rjf: calling a lens? -> generate IR for the first argument; wrap the type in // a lens type, which preserves the name & arguments of the lens call expression - if(lhs_type->kind == E_TypeKind_LensSpec) + else if(lhs_type->kind == E_TypeKind_LensSpec) { Temp scratch = scratch_begin(&arena, 1); @@ -2202,6 +2183,8 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) scratch_end(scratch); } + + // rjf: calling any other type? -> not valid else { e_msgf(arena, &result.msgs, E_MsgKind_InterpretationError, expr->location, "Calling this type is not supported."); diff --git a/src/eval/eval_parse.c b/src/eval/eval_parse.c index 9c46201f..9296befb 100644 --- a/src/eval/eval_parse.c +++ b/src/eval/eval_parse.c @@ -1218,29 +1218,31 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray tok // rjf: advance past operator it += 1; - // rjf: parse right-hand-side - E_Parse rhs_expr_parse = e_parse_expr_from_text_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), 0, 1); - e_msg_list_concat_in_place(&result.msgs, &rhs_expr_parse.msgs); - E_Expr *rhs = rhs_expr_parse.exprs.last; - it = rhs_expr_parse.last_token; + // rjf: look for member name + E_Token member_name_maybe = e_token_at_it(it, &tokens); + String8 member_name_maybe_string = str8_substr(text, member_name_maybe.range); - // rjf: produce member access expr - if(rhs == &e_expr_nil) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token_string.str, "Missing right-hand-side of `.`."); - } - else + // rjf: if we have a member name, build dot-operator tree + if(member_name_maybe.kind == E_TokenKind_Identifier) { + it += 1; E_Expr *lhs = atom; + E_Expr *rhs = e_push_expr(arena, E_ExprKind_LeafIdentifier, member_name_maybe_string.str); + rhs->string = member_name_maybe_string; atom = e_push_expr(arena, E_ExprKind_MemberAccess, token_string.str); e_expr_push_child(atom, lhs); e_expr_push_child(atom, rhs); } + + // rjf: no identifier after `.`? -> error + else + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token_string.str, "Missing identifier after `.`."); + } } // rjf: array index - if(max_precedence >= 1 && - token.kind == E_TokenKind_Symbol && + if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("["), 0)) { is_postfix_unary = 1; @@ -1279,8 +1281,7 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray tok } // rjf: calls - if(max_precedence >= 0 && - token.kind == E_TokenKind_Symbol && + if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("("), 0)) { is_postfix_unary = 1; diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index ca2886b6..a03768bd 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -1531,7 +1531,6 @@ ev_escaped_from_raw_string(Arena *arena, String8 raw) 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) { @@ -1796,123 +1795,128 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string) break; } } - if(module != &e_module_nil) + RDI_Parsed *rdi = module->rdi; + U64 voff = vaddr - module->vaddr_range.min; + B32 good_symbol_match = 0; + + // NOTE(rjf): read-only -> generate non-parseable things, like type-info / inlines + if(params->flags & EV_StringFlag_ReadOnlyDisplayRules) { - RDI_Parsed *rdi = module->rdi; - U64 voff = vaddr - module->vaddr_range.min; - B32 good_symbol_match = 0; + // rjf: voff -> scope + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); - // NOTE(rjf): read-only -> generate non-parseable things, like type-info / inlines - if(params->flags & EV_StringFlag_ReadOnlyDisplayRules) + // rjf: scope -> # of max possible inline depth + U64 inline_site_count = 0; + for(U64 s_idx = scope_idx, s_idx_next = 0; s_idx != 0; s_idx = s_idx_next) { - // rjf: voff -> scope - U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); - - // rjf: scope -> # of max possible inline depth - U64 inline_site_count = 0; + RDI_Scope *s = rdi_element_from_name_idx(rdi, Scopes, s_idx); + s_idx_next = s->parent_scope_idx; + if(s->inline_site_idx != 0) + { + inline_site_count += 1; + } + else + { + break; + } + } + + // rjf: depth in [1, max]? -> form name from inline site + if(0 < ptr_data->type->depth && ptr_data->type->depth <= inline_site_count) + { + RDI_InlineSite *inline_site = 0; + U64 s_inline_depth = inline_site_count; for(U64 s_idx = scope_idx, s_idx_next = 0; s_idx != 0; s_idx = s_idx_next) { RDI_Scope *s = rdi_element_from_name_idx(rdi, Scopes, s_idx); s_idx_next = s->parent_scope_idx; - if(s->inline_site_idx != 0) + if(s_inline_depth == ptr_data->type->depth) { - inline_site_count += 1; + inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); + break; } - else + s_inline_depth -= 1; + if(s_inline_depth == 0) { break; } } - - // rjf: depth in [1, max]? -> form name from inline site - if(0 < ptr_data->type->depth && ptr_data->type->depth <= inline_site_count) + if(inline_site != 0) { - RDI_InlineSite *inline_site = 0; - U64 s_inline_depth = inline_site_count; - for(U64 s_idx = scope_idx, s_idx_next = 0; s_idx != 0; s_idx = s_idx_next) - { - RDI_Scope *s = rdi_element_from_name_idx(rdi, Scopes, s_idx); - s_idx_next = s->parent_scope_idx; - if(s_inline_depth == ptr_data->type->depth) - { - inline_site = rdi_element_from_name_idx(rdi, InlineSites, s->inline_site_idx); - break; - } - s_inline_depth -= 1; - if(s_inline_depth == 0) - { - break; - } - } - if(inline_site != 0) - { - E_TypeKey type = e_type_key_ext(E_TypeKind_Function, inline_site->type_idx, module_idx); - String8 name = {0}; - name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); - if(inline_site->type_idx != 0) - { - Temp scratch = scratch_begin(&arena, 1); - String8List list = {0}; - str8_list_pushf(scratch.arena, &list, "[inlined] "); - e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0); - str8_list_push(scratch.arena, &list, name); - e_type_rhs_string_from_key(scratch.arena, type, &list, 0); - *out_string = str8_list_join(arena, &list, 0); - scratch_end(scratch); - } - else - { - *out_string = push_str8_copy(arena, name); - } - good_symbol_match = (name.size != 0); - } - } - - // rjf: depth == 0 or depth >= max? -> form name from scope procedure - else - { - Temp scratch = scratch_begin(&arena, 1); - RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); - U64 proc_idx = scope->proc_idx; - RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); - E_TypeKey type = e_type_key_ext(E_TypeKind_Function, procedure->type_idx, module_idx); + E_TypeKey type = e_type_key_ext(E_TypeKind_Function, inline_site->type_idx, module_idx); String8 name = {0}; - name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size); - if(procedure->type_idx != 0) + name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size); + if(inline_site->type_idx != 0) { + Temp scratch = scratch_begin(&arena, 1); String8List list = {0}; + str8_list_pushf(scratch.arena, &list, "[inlined] "); e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0); str8_list_push(scratch.arena, &list, name); e_type_rhs_string_from_key(scratch.arena, type, &list, 0); *out_string = str8_list_join(arena, &list, 0); + scratch_end(scratch); } else { *out_string = push_str8_copy(arena, name); } - good_symbol_match = (out_string->size != 0); - scratch_end(scratch); + good_symbol_match = (name.size != 0); } } - // NOTE(rjf): non-read-only -> only generate thing which can be parsed, so just procedure name + // rjf: depth == 0 or depth >= max? -> form name from scope procedure else { - // rjf: voff -> scope - U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); - RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); + Temp scratch = scratch_begin(&arena, 1); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, scope_idx); + U64 proc_idx = scope->proc_idx; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx); + E_TypeKey type = e_type_key_ext(E_TypeKind_Function, procedure->type_idx, module_idx); + String8 name = {0}; + name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size); + if(procedure->type_idx != 0) + { + String8List list = {0}; + e_type_lhs_string_from_key(scratch.arena, type, &list, 0, 0); + str8_list_push(scratch.arena, &list, name); + e_type_rhs_string_from_key(scratch.arena, type, &list, 0); + *out_string = str8_list_join(arena, &list, 0); + } + else + { + *out_string = push_str8_copy(arena, name); + } - // rjf: scope -> procedure / string - RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope); - String8 procedure_name = {0}; - procedure_name.str = rdi_name_from_procedure(rdi, procedure, &procedure_name.size); - - *out_string = procedure_name; - good_symbol_match = (procedure_name.size != 0); + good_symbol_match = (out_string->size != 0); + scratch_end(scratch); } - ptr_data->did_prefix_content = good_symbol_match; + // rjf: if we have a function type, but we did not generate any name, then just put a ??? + if(out_string->size == 0 && e_type_kind_from_key(ptr_data->type->direct_type_key) == E_TypeKind_Function) + { + *out_string = str8_lit("???"); + good_symbol_match = 1; + } } + + // NOTE(rjf): non-read-only -> only generate thing which can be parsed, so just procedure name + else + { + // rjf: voff -> scope + U64 scope_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_ScopeVMap, voff); + RDI_Scope *scope = rdi_scope_from_voff(rdi, voff); + + // rjf: scope -> procedure / string + RDI_Procedure *procedure = rdi_procedure_from_scope(rdi, scope); + String8 procedure_name = {0}; + procedure_name.str = rdi_name_from_procedure(rdi, procedure, &procedure_name.size); + + *out_string = procedure_name; + good_symbol_match = (procedure_name.size != 0); + } + + ptr_data->did_prefix_content = good_symbol_match; } // rjf: if this is an array, and we do not have a prefix, then we need to diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 270b02dd..21d64a88 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -824,7 +824,7 @@ rd_id_from_watch_cell(RD_WatchCell *cell) result = e_hash_from_string(result, str8_struct(&cell->kind)); if(cell->kind != RD_WatchCellKind_Expr) { - result = e_hash_from_string(result, str8_struct(&cell->eval.irtree.mode)); + // result = e_hash_from_string(result, str8_struct(&cell->eval.irtree.mode)); result = e_hash_from_string(result, str8_struct(&cell->index)); result = e_hash_from_string(result, str8_struct(&cell->default_pct)); } @@ -1289,7 +1289,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) F32 next_pct = 0; #define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct) rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .default_pct = 0.65f, .pct = take_pct()); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("hex((U64)($expr))"), .default_pct = 0.20f, .pct = take_pct()); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("lens:hex((U64)($expr))"), .default_pct = 0.20f, .pct = take_pct()); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Tag, .default_pct = 0.15f, .pct = take_pct()); #undef take_pct } @@ -1313,8 +1313,11 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) #define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct) rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_CallStackFrame, .default_pct = 0.05f, .pct = take_pct()); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .default_pct = 0.55f, .pct = take_pct()); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("hex((U64)($expr))"), .default_pct = 0.20f, .pct = take_pct()); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .eval = module_eval, .default_pct = 0.20f, .pct = take_pct()); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("lens:hex((U64)($expr))"), .default_pct = 0.20f, .pct = take_pct()); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, + .eval = (module == &ctrl_entity_nil ? (E_Eval)zero_struct : module_eval), + .string = str8_lit(" "), + .default_pct = 0.20f, .pct = take_pct()); #undef take_pct }