From f9abd3efb96315411384ca3f0ae960be31750895 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 11 Nov 2024 16:06:01 -0800 Subject: [PATCH] first half of first pass at asynchronous name matching; simplify current name matching path used in syntax highlighting & deduplicate between code slice & code labels --- src/dbgi/dbgi.c | 256 ++++++++++++++++++++++++++++++++++-- src/dbgi/dbgi.h | 87 +++++++++++- src/raddbg/raddbg_core.c | 79 +++++++++++ src/raddbg/raddbg_core.h | 3 +- src/raddbg/raddbg_widgets.c | 110 ++-------------- 5 files changed, 429 insertions(+), 106 deletions(-) diff --git a/src/dbgi/dbgi.c b/src/dbgi/dbgi.c index c6a73889..f564da28 100644 --- a/src/dbgi/dbgi.c +++ b/src/dbgi/dbgi.c @@ -81,16 +81,24 @@ di_key_array_from_list(Arena *arena, DI_KeyList *list) return array; } +internal DI_KeyArray +di_key_array_copy(Arena *arena, DI_KeyArray *src) +{ + DI_KeyArray dst = {0}; + dst.v = push_array(arena, DI_Key, dst.count); + for EachIndex(idx, dst.count) + { + dst.v[idx] = di_key_copy(arena, &src->v[idx]); + } + return dst; +} + internal DI_SearchParams di_search_params_copy(Arena *arena, DI_SearchParams *src) { DI_SearchParams dst = {0}; MemoryCopyStruct(&dst, src); - dst.dbgi_keys.v = push_array(arena, DI_Key, dst.dbgi_keys.count); - for EachIndex(idx, dst.dbgi_keys.count) - { - dst.dbgi_keys.v[idx] = di_key_copy(arena, &src->dbgi_keys.v[idx]); - } + dst.dbgi_keys = di_key_array_copy(arena, &dst.dbgi_keys); return dst; } @@ -631,7 +639,6 @@ di_search_items_from_key_params_query(DI_Scope *scope, U128 key, DI_SearchParams DI_SearchItemArray items = {0}; { U64 params_hash = di_hash_from_search_params(params); - U64 thread_idx = key.u64[0]%di_shared->search_threads_count; U64 slot_idx = key.u64[0]%di_shared->search_slots_count; U64 stripe_idx = slot_idx%di_shared->search_stripes_count; DI_SearchSlot * slot = &di_shared->search_slots[slot_idx]; @@ -692,7 +699,7 @@ di_search_items_from_key_params_query(DI_Scope *scope, U128 key, DI_SearchParams node->buckets[new_bucket_idx].query = push_str8_copy(node->buckets[new_bucket_idx].arena, query); node->buckets[new_bucket_idx].params = di_search_params_copy(node->buckets[new_bucket_idx].arena, params); node->buckets[new_bucket_idx].params_hash = params_hash; - di_u2s_enqueue_req(thread_idx, key, endt_us); + di_u2s_enqueue_req(key, endt_us); } // rjf: not stale, or timeout -> break @@ -1122,9 +1129,10 @@ ASYNC_WORK_DEF(di_parse_work) //~ rjf: Search Threads internal B32 -di_u2s_enqueue_req(U64 thread_idx, U128 key, U64 endt_us) +di_u2s_enqueue_req(U128 key, U64 endt_us) { B32 result = 0; + U64 thread_idx = key.u64[0]%di_shared->search_threads_count; DI_SearchThread *thread = &di_shared->search_threads[thread_idx]; OS_MutexScope(thread->ring_mutex) for(;;) { @@ -1482,3 +1490,235 @@ di_search_thread__entry_point(void *p) scratch_end(scratch); } } + +//////////////////////////////// +//~ rjf: Match Store + +internal DI_MatchStore * +di_match_store_alloc(void) +{ + Arena *arena = arena_alloc(); + DI_MatchStore *store = push_array(arena, DI_MatchStore, 1); + store->arena = arena; + for EachElement(idx, store->gen_arenas) + { + store->gen_arenas[idx] = arena_alloc(); + } + store->params_arena = arena_alloc(); + store->params_rw_mutex = os_rw_mutex_alloc(); + store->match_name_slots_count = 4096; + store->match_name_slots = push_array(arena, DI_MatchNameSlot, store->match_name_slots_count); + store->u2m_ring_cv = os_condition_variable_alloc(); + store->u2m_ring_mutex = os_mutex_alloc(); + store->u2m_ring_size = KB(64); + store->u2m_ring_base = push_array_no_zero(arena, U8, store->u2m_ring_size); + store->m2u_ring_cv = os_condition_variable_alloc(); + store->m2u_ring_mutex = os_mutex_alloc(); + store->m2u_ring_size = KB(64); + store->m2u_ring_base = push_array_no_zero(arena, U8, store->m2u_ring_size); + return store; +} + +internal void +di_match_store_begin(DI_MatchStore *store, DI_KeyArray keys) +{ + store->gen += 1; + arena_clear(store->gen_arenas[store->gen%ArrayCount(store->gen_arenas)]); + + // rjf: hash parameters + U64 params_hash = 5381; + for EachIndex(idx, keys.count) + { + params_hash = di_hash_from_seed_string(params_hash, str8_struct(&keys.v[idx].min_timestamp), 0); + params_hash = di_hash_from_seed_string(params_hash, keys.v[idx].path, StringMatchFlag_CaseInsensitive); + } + + // rjf: store parameters if needed + if(store->params_hash != params_hash) OS_MutexScopeW(store->params_rw_mutex) + { + arena_clear(store->params_arena); + store->params_hash = params_hash; + store->params_keys = di_key_array_copy(store->params_arena, &keys); + } + + // rjf: prune least recently used matches + { + for(DI_MatchNameNode *node = store->last_lru_match_name, *prev = 0; node != 0; node = prev) + { + prev = node->prev; + if(node->last_gen_touched+1 != store->gen) + { + U64 slot_idx = node->hash%store->match_name_slots_count; + DI_MatchNameSlot *slot = &store->match_name_slots[slot_idx]; + DLLRemove_NP(store->first_lru_match_name, store->last_lru_match_name, node, lru_next, lru_prev); + DLLRemove(slot->first, slot->last, node); + SLLStackPush(store->first_free_match_name, node); + } + } + } +} + +internal B32 +di_match_store_name_has_matches(DI_MatchStore *store, String8 name, U64 endt_us) +{ + B32 result = 0; + { + // rjf: unpack name + U64 hash = di_hash_from_string(name, 0); + U64 slot_idx = hash%store->match_name_slots_count; + DI_MatchNameSlot *slot = &store->match_name_slots[slot_idx]; + + // rjf: get name's node, if it exists + DI_MatchNameNode *node = 0; + for(DI_MatchNameNode *n = slot->first; n != 0; n = n->next) + { + if(n->hash == hash && str8_match(n->name, name, 0)) + { + node = n; + break; + } + } + + // rjf: if node does not exist, create + if(node == 0) + { + node = store->first_free_match_name; + if(node) + { + SLLStackPop(store->first_free_match_name); + } + else + { + node = push_array_no_zero(store->arena, DI_MatchNameNode, 1); + } + MemoryZeroStruct(node); + node->hash = hash; + DLLPushBack(slot->first, slot->last, node); + node->first_gen_touched = store->gen; + DLLInsert_NP(store->first_lru_match_name, store->last_lru_match_name, (DI_MatchNameNode *)0, node, lru_next, lru_prev); + } + + // rjf: touch node for this gen + node->last_gen_touched = store->gen; + node->name = push_str8_copy(store->gen_arenas[store->gen%ArrayCount(store->gen_arenas)], name); + DLLRemove_NP(store->first_lru_match_name, store->last_lru_match_name, node, lru_next, lru_prev); + DLLInsert_NP(store->first_lru_match_name, store->last_lru_match_name, (DI_MatchNameNode *)0, node, lru_next, lru_prev); + + // rjf: if this node is new, request it for the given parameters + if(node->req_params_hash != store->params_hash) + { + B32 sent = 0; + OS_MutexScope(store->u2m_ring_mutex) for(;;) + { + U64 unconsumed_size = store->u2m_ring_write_pos - store->u2m_ring_read_pos; + U64 available_size = store->u2m_ring_size - unconsumed_size; + if(available_size >= sizeof(U64) + name.size) + { + store->u2m_ring_write_pos += ring_write_struct(store->u2m_ring_base, store->u2m_ring_size, store->u2m_ring_write_pos, &name.size); + store->u2m_ring_write_pos += ring_write(store->u2m_ring_base, store->u2m_ring_size, store->u2m_ring_write_pos, name.str, name.size); + sent = 1; + break; + } + if(os_now_microseconds() >= endt_us) + { + break; + } + os_condition_variable_wait(store->u2m_ring_cv, store->u2m_ring_mutex, endt_us); + } + if(sent) + { + os_condition_variable_broadcast(store->u2m_ring_cv); + async_push_work(di_match_work, .input = store); + node->req_params_hash = store->params_hash; + } + } + + // rjf: if this node's state is stale, consume results from match work & store them + if(node->req_params_hash != node->cmp_params_hash) + { + for(B32 done = 0; !done && os_now_microseconds() < endt_us;) + { + Temp scratch = scratch_begin(0, 0); + + // rjf: get next result + String8 result_name = {0}; + U64 result_params_hash = 0; + U64 result_dbgi_idx = 0; + RDI_SectionKind result_section_kind = RDI_SectionKind_NULL; + U32 result_idx = 0; + OS_MutexScope(store->m2u_ring_mutex) for(;;) + { + U64 unconsumed_size = store->m2u_ring_write_pos - store->m2u_ring_read_pos; + if(unconsumed_size >= sizeof(U64)*4) + { + store->m2u_ring_read_pos += ring_read_struct(store->m2u_ring_base, store->m2u_ring_size, store->m2u_ring_read_pos, &result_name.size); + result_name.str = push_array(scratch.arena, U8, result_name.size); + store->m2u_ring_read_pos += ring_read(store->m2u_ring_base, store->m2u_ring_size, store->m2u_ring_read_pos, result_name.str, result_name.size); + store->m2u_ring_read_pos += ring_read_struct(store->m2u_ring_base, store->m2u_ring_size, store->m2u_ring_read_pos, &result_params_hash); + store->m2u_ring_read_pos += ring_read_struct(store->m2u_ring_base, store->m2u_ring_size, store->m2u_ring_read_pos, &result_dbgi_idx); + store->m2u_ring_read_pos += ring_read_struct(store->m2u_ring_base, store->m2u_ring_size, store->m2u_ring_read_pos, &result_section_kind); + store->m2u_ring_read_pos += ring_read_struct(store->m2u_ring_base, store->m2u_ring_size, store->m2u_ring_read_pos, &result_idx); + break; + } + if(os_now_microseconds() >= endt_us) + { + break; + } + os_condition_variable_wait(store->m2u_ring_cv, store->m2u_ring_mutex, endt_us); + } + os_condition_variable_broadcast(store->m2u_ring_cv); + + // rjf: store result + U64 result_hash = di_hash_from_string(result_name, 0); + U64 result_slot_idx = result_hash%store->match_name_slots_count; + DI_MatchNameSlot *result_slot = &store->match_name_slots[slot_idx]; + for(DI_MatchNameNode *n = result_slot->first; n != 0; n = n->next) + { + if(n->hash == result_hash && str8_match(result_name, n->name, 0)) + { + n->cmp_params_hash = result_params_hash; + n->has_matches = (result_idx != 0); + break; + } + } + + // rjf: we're done if we got the hash we were looking for + if(result_hash == hash) + { + done = 1; + } + + scratch_end(scratch); + } + } + + // rjf: return node present info + result = node->has_matches; + } + return result; +} + +ASYNC_WORK_DEF(di_match_work) +{ + Temp scratch = scratch_begin(0, 0); + DI_MatchStore *store = (DI_MatchStore *)input; + { + //- rjf: get next name + String8 name = {0}; + OS_MutexScope(store->u2m_ring_mutex) for(;;) + { + U64 unconsumed_size = store->u2m_ring_write_pos - store->u2m_ring_read_pos; + if(unconsumed_size >= sizeof(U64)) + { + store->u2m_ring_read_pos += ring_read_struct(store->u2m_ring_base, store->u2m_ring_size, store->u2m_ring_read_pos, &name.size); + name.str = push_array(scratch.arena, U8, name.size); + store->u2m_ring_read_pos += ring_read(store->u2m_ring_base, store->u2m_ring_size, store->u2m_ring_read_pos, name.str, name.size); + break; + } + os_condition_variable_wait(store->u2m_ring_cv, store->u2m_ring_mutex, max_U64); + } + os_condition_variable_broadcast(store->u2m_ring_cv); + } + scratch_end(scratch); + return 0; +} diff --git a/src/dbgi/dbgi.h b/src/dbgi/dbgi.h index 03781f13..8ab168ad 100644 --- a/src/dbgi/dbgi.h +++ b/src/dbgi/dbgi.h @@ -253,6 +253,82 @@ struct DI_SearchThread U64 ring_read_pos; }; +//////////////////////////////// +//~ rjf: Match Cache State Types + +typedef struct DI_Match DI_Match; +struct DI_Match +{ + DI_Match *next; + DI_Match *prev; + U64 dbgi_idx; + RDI_SectionKind section; + U32 idx; +}; + +typedef struct DI_MatchNameNode DI_MatchNameNode; +struct DI_MatchNameNode +{ + DI_MatchNameNode *next; + DI_MatchNameNode *prev; + DI_MatchNameNode *lru_next; + DI_MatchNameNode *lru_prev; + U64 first_gen_touched; + U64 last_gen_touched; + U64 req_params_hash; + U64 cmp_params_hash; + String8 name; + U64 hash; + B32 has_matches; + // DI_Match *first_match; + // DI_Match *last_match; +}; + +typedef struct DI_MatchNameSlot DI_MatchNameSlot; +struct DI_MatchNameSlot +{ + DI_MatchNameNode *first; + DI_MatchNameNode *last; +}; + +typedef struct DI_MatchStore DI_MatchStore; +struct DI_MatchStore +{ + Arena *arena; + U64 gen; + Arena *gen_arenas[2]; + + // rjf: parameters + Arena *params_arena; + OS_Handle params_rw_mutex; + U64 params_hash; + DI_KeyArray params_keys; + + // rjf: match cache + U64 match_name_slots_count; + DI_MatchNameSlot *match_name_slots; + DI_MatchNameNode *first_free_match_name; + DI_Match *first_free_match; + DI_MatchNameNode *first_lru_match_name; + DI_MatchNameNode *last_lru_match_name; + + // rjf: user -> match work ring buffer + OS_Handle u2m_ring_cv; + OS_Handle u2m_ring_mutex; + U64 u2m_ring_size; + U8 *u2m_ring_base; + U64 u2m_ring_write_pos; + U64 u2m_ring_read_pos; + + // rjf: match work -> user ring buffer + OS_Handle m2u_ring_cv; + OS_Handle m2u_ring_mutex; + U64 m2u_ring_size; + U8 *m2u_ring_base; + U64 m2u_ring_write_pos; + U64 m2u_ring_read_pos; +}; + //////////////////////////////// //~ rjf: Shared State Types @@ -313,6 +389,7 @@ internal DI_Key di_key_copy(Arena *arena, DI_Key *src); internal DI_Key di_normalized_key_from_key(Arena *arena, DI_Key *src); internal void di_key_list_push(Arena *arena, DI_KeyList *list, DI_Key *key); internal DI_KeyArray di_key_array_from_list(Arena *arena, DI_KeyList *list); +internal DI_KeyArray di_key_array_copy(Arena *arena, DI_KeyArray *src); internal DI_SearchParams di_search_params_copy(Arena *arena, DI_SearchParams *src); internal U64 di_hash_from_search_params(DI_SearchParams *params); internal void di_search_item_chunk_list_concat_in_place(DI_SearchItemChunkList *dst, DI_SearchItemChunkList *to_push); @@ -374,11 +451,19 @@ ASYNC_WORK_DEF(di_parse_work); //////////////////////////////// //~ rjf: Search Threads -internal B32 di_u2s_enqueue_req(U64 thread_idx, U128 key, U64 endt_us); +internal B32 di_u2s_enqueue_req(U128 key, U64 endt_us); internal U128 di_u2s_dequeue_req(U64 thread_idx); ASYNC_WORK_DEF(di_search_work); internal int di_qsort_compare_search_items(DI_SearchItem *a, DI_SearchItem *b); internal void di_search_thread__entry_point(void *p); +//////////////////////////////// +//~ rjf: Match Store + +internal DI_MatchStore *di_match_store_alloc(void); +internal void di_match_store_begin(DI_MatchStore *store, DI_KeyArray keys); +internal B32 di_match_store_name_has_matches(DI_MatchStore *store, String8 name, U64 endt_us); +ASYNC_WORK_DEF(di_match_work); + #endif // DBGI_H diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 4991ea6e..cb76b6e4 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -10321,6 +10321,85 @@ rd_theme_color_from_txt_token_kind(TXT_TokenKind kind) return color; } +internal RD_ThemeColor +rd_theme_color_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8 string) +{ + RD_ThemeColor color = RD_ThemeColor_CodeDefault; + if(kind == TXT_TokenKind_Identifier || kind == TXT_TokenKind_Keyword) + { + CTRL_Entity *module = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->module); + DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); + B32 mapped = 0; + + // rjf: try to map as local + if(!mapped && kind == TXT_TokenKind_Identifier) + { + U64 local_num = e_num_from_string(e_parse_ctx->locals_map, string); + if(local_num != 0) + { + mapped = 1; + color = RD_ThemeColor_CodeLocal; + } + } + + // rjf: try to map as member + if(!mapped && kind == TXT_TokenKind_Identifier) + { + U64 member_num = e_num_from_string(e_parse_ctx->member_map, string); + if(member_num != 0) + { + mapped = 1; + color = RD_ThemeColor_CodeLocal; + } + } + + // rjf: try to map as register + if(!mapped) + { + U64 reg_num = e_num_from_string(e_parse_ctx->regs_map, string); + if(reg_num != 0) + { + mapped = 1; + color = RD_ThemeColor_CodeRegister; + } + } + + // rjf: try to map as register alias + if(!mapped) + { + U64 alias_num = e_num_from_string(e_parse_ctx->reg_alias_map, string); + if(alias_num != 0) + { + mapped = 1; + color = RD_ThemeColor_CodeRegister; + } + } + + // rjf: try to map as symbol + if(!mapped && kind == TXT_TokenKind_Identifier) + { + U64 voff = d_voff_from_dbgi_key_symbol_name(&dbgi_key, string); + if(voff != 0) + { + mapped = 1; + color = RD_ThemeColor_CodeSymbol; + } + } + + // rjf: try to map as type + if(!mapped && kind == TXT_TokenKind_Identifier) + { + U64 type_num = d_type_num_from_dbgi_key_name(&dbgi_key, string); + if(type_num != 0) + { + mapped = 1; + color = RD_ThemeColor_CodeType; + } + } + } + return color; +} + //- rjf: code -> palette internal UI_Palette * diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 01d0462b..deb20e44 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -1398,7 +1398,8 @@ internal String8List rd_cmd_name_list_from_binding(Arena *arena, RD_Binding bind //- rjf: colors internal Vec4F32 rd_rgba_from_theme_color(RD_ThemeColor color); -internal RD_ThemeColor rd_theme_color_from_txt_token_kind(TXT_TokenKind kind); +internal RD_ThemeColor rd_theme_color_from_txt_token_kind(TXT_TokenKind kind); +internal RD_ThemeColor rd_theme_color_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8 string); //- rjf: code -> palette internal UI_Palette *rd_palette_from_code(RD_PaletteCode code); diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index cc2af029..62c93ee5 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -2138,88 +2138,14 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe } // rjf: token -> token color - Vec4F32 token_color = rd_rgba_from_theme_color(RD_ThemeColor_CodeDefault); + RD_ThemeColor token_theme_color = rd_theme_color_from_txt_token_kind(token->kind); + RD_ThemeColor lookup_theme_color = rd_theme_color_from_txt_token_kind_lookup_string(token->kind, token_string); + Vec4F32 token_color = rd_rgba_from_theme_color(token_theme_color); + if(lookup_theme_color != RD_ThemeColor_CodeDefault) { - RD_ThemeColor new_color_kind = rd_theme_color_from_txt_token_kind(token->kind); - F32 mix_t = 1.f; - if(token->kind == TXT_TokenKind_Identifier || token->kind == TXT_TokenKind_Keyword) - { - B32 mapped_special = 0; - for(DI_KeyNode *n = params->relevant_dbgi_keys.first; n != 0; n = n->next) - { - DI_Key dbgi_key = n->v; - UI_Key dbgi_anim_key = ui_key_from_stringf(ui_key_zero(), "###dbgi_alive_t_%S", dbgi_key.path); - if(!mapped_special && token->kind == TXT_TokenKind_Identifier) - { - U64 voff = d_voff_from_dbgi_key_symbol_name(&dbgi_key, token_string); - if(voff != 0) - { - mapped_special = 1; - new_color_kind = RD_ThemeColor_CodeSymbol; - mix_t = ui_anim(dbgi_anim_key, 1.f); - } - } - if(!mapped_special && token->kind == TXT_TokenKind_Identifier) - { - U64 type_num = d_type_num_from_dbgi_key_name(&dbgi_key, token_string); - if(type_num != 0) - { - mapped_special = 1; - new_color_kind = RD_ThemeColor_CodeType; - mix_t = ui_anim(dbgi_anim_key, 1.f); - } - } - break; - } - if(!mapped_special && token->kind == TXT_TokenKind_Identifier) - { - U64 local_num = e_num_from_string(e_parse_ctx->locals_map, token_string); - if(local_num != 0) - { - mapped_special = 1; - new_color_kind = RD_ThemeColor_CodeLocal; - mix_t = selected_thread_module_alive_t; - } - } - if(!mapped_special && token->kind == TXT_TokenKind_Identifier) - { - U64 member_num = e_num_from_string(e_parse_ctx->member_map, token_string); - if(member_num != 0) - { - mapped_special = 1; - new_color_kind = RD_ThemeColor_CodeLocal; - mix_t = selected_thread_module_alive_t; - } - } - if(!mapped_special) - { - U64 reg_num = e_num_from_string(e_parse_ctx->regs_map, token_string); - if(reg_num != 0) - { - mapped_special = 1; - new_color_kind = RD_ThemeColor_CodeRegister; - mix_t = selected_thread_arch_alive_t; - } - } - if(!mapped_special) - { - U64 alias_num = e_num_from_string(e_parse_ctx->reg_alias_map, token_string); - if(alias_num != 0) - { - mapped_special = 1; - new_color_kind = RD_ThemeColor_CodeRegister; - mix_t = selected_thread_arch_alive_t; - } - } - } - if(new_color_kind != RD_ThemeColor_Null) - { - Vec4F32 t_color = rd_rgba_from_theme_color(new_color_kind); - token_color.x += (t_color.x - token_color.x) * mix_t; - token_color.y += (t_color.y - token_color.y) * mix_t; - token_color.z += (t_color.z - token_color.z) * mix_t; - token_color.w += (t_color.w - token_color.w) * mix_t; - } + Vec4F32 lookup_color = rd_rgba_from_theme_color(lookup_theme_color); + F32 lookup_color_mix_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "%S_lookup", token_string), 1.f); + token_color = mix_4f32(token_color, lookup_color, lookup_color_mix_t); } // rjf: push fancy string @@ -2727,28 +2653,20 @@ rd_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_s dr_fancy_string_list_push(arena, &fancy_strings, &fancy_string); }break; case TXT_TokenKind_Identifier: + case TXT_TokenKind_Keyword: { - E_TypeKey type = e_leaf_type_from_name(token_string); - Vec4F32 color = base_color; - if(!e_type_key_match(e_type_key_zero(), type)) + RD_ThemeColor lookup_theme_color = rd_theme_color_from_txt_token_kind_lookup_string(token->kind, token_string); + if(lookup_theme_color != RD_ThemeColor_CodeDefault) { - color = rd_rgba_from_theme_color(RD_ThemeColor_CodeType); - } - else - { - CTRL_Entity *module = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->module); - DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); - U64 symbol_voff = d_voff_from_dbgi_key_symbol_name(&dbgi_key, token_string); - if(symbol_voff != 0) - { - color = rd_rgba_from_theme_color(RD_ThemeColor_CodeSymbol); - } + Vec4F32 lookup_color = rd_rgba_from_theme_color(lookup_theme_color); + F32 lookup_color_mix_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "%S_lookup", token_string), 1.f); + token_color_rgba = mix_4f32(token_color_rgba, lookup_color, lookup_color_mix_t); } DR_FancyString fancy_string = { ui_top_font(), token_string, - color, + token_color_rgba, ui_top_font_size() * (1.f - !!indirection_size_change*(indirection_counter/10.f)), }; dr_fancy_string_list_push(arena, &fancy_strings, &fancy_string);