diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index ffa258d2..f33b082d 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -4695,10 +4695,12 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread) ctx->member_map = e_push_member_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff); ctx->macro_map = push_array(arena, E_String2ExprMap, 1); ctx->macro_map[0] = e_string2expr_map_make(arena, 512); +#if 0 // TODO(rjf): @eval ctx->lookup_rule_map = push_array(arena, E_LookupRuleMap, 1); ctx->lookup_rule_map[0] = e_lookup_rule_map_make(arena, 512); ctx->irgen_rule_map = push_array(arena, E_IRGenRuleMap, 1); ctx->irgen_rule_map[0] = e_irgen_rule_map_make(arena, 512); +#endif ctx->auto_hook_map = push_array(arena, E_AutoHookMap, 1); ctx->auto_hook_map[0] = e_auto_hook_map_make(arena, 512); } diff --git a/src/eval/eval_bundles.c b/src/eval/eval_bundles.c index 87c45e0c..263159d5 100644 --- a/src/eval/eval_bundles.c +++ b/src/eval/eval_bundles.c @@ -6,17 +6,9 @@ internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr) -{ - E_ExprChain exprs = {expr, expr}; - E_Eval result = e_eval_from_exprs(arena, exprs); - return result; -} - -internal E_Eval -e_eval_from_exprs(Arena *arena, E_ExprChain exprs) { ProfBeginFunction(); - E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, exprs.last); + 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); @@ -24,7 +16,7 @@ e_eval_from_exprs(Arena *arena, E_ExprChain exprs) { .value = interp.value, .space = interp.space, - .exprs = exprs, + .expr = expr, .irtree = irtree, .bytecode = bytecode, .code = interp.code, @@ -43,7 +35,7 @@ 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_exprs(arena, parse.exprs); + E_Eval eval = e_eval_from_expr(arena, parse.exprs.first); e_msg_list_concat_in_place(&eval.msgs, &parse.msgs); return eval; } @@ -252,22 +244,22 @@ e_value_from_expr(E_Expr *expr) E_Value result = value_eval.value; scratch_end(scratch); return result; -} - +} + //////////////////////////////// //~ rjf: Debug Logging Functions -internal String8 -e_debug_log_from_expr_string(Arena *arena, String8 string) -{ - Temp scratch = scratch_begin(&arena, 1); - char *indent_spaces = " "; - String8List strings = {0}; - +internal String8 +e_debug_log_from_expr_string(Arena *arena, String8 string) +{ + Temp scratch = scratch_begin(&arena, 1); + char *indent_spaces = " "; + String8List strings = {0}; + //- rjf: begin expression String8 expr_text = string; str8_list_pushf(scratch.arena, &strings, "`%S`\n", expr_text); - + //- rjf: tokenize E_TokenArray tokens = e_token_array_from_text(scratch.arena, expr_text); str8_list_pushf(scratch.arena, &strings, " tokens:\n"); @@ -277,7 +269,7 @@ e_debug_log_from_expr_string(Arena *arena, String8 string) String8 token_string = str8_substr(expr_text, token.range); str8_list_pushf(scratch.arena, &strings, " %S: `%S`\n", e_token_kind_strings[token.kind], token_string); } - + //- rjf: parse E_Parse parse = e_parse_expr_from_text_tokens(scratch.arena, expr_text, tokens); { @@ -320,7 +312,7 @@ e_debug_log_from_expr_string(Arena *arena, String8 string) } } } - + //- rjf: type E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, parse.exprs.first); { @@ -335,7 +327,7 @@ e_debug_log_from_expr_string(Arena *arena, String8 string) str8_list_pushf(scratch.arena, &strings, "%.*s%S\n", (int)indent*4, indent_spaces, e_type_kind_basic_string_table[type->kind]); } } - + //- rjf: irtree { typedef struct Task Task; @@ -376,10 +368,10 @@ e_debug_log_from_expr_string(Arena *arena, String8 string) } } } - - str8_list_pushf(scratch.arena, &strings, "\n"); - - String8 result = str8_list_join(arena, &strings, 0); - scratch_end(scratch); - return result; -} + + str8_list_pushf(scratch.arena, &strings, "\n"); + + String8 result = str8_list_join(arena, &strings, 0); + scratch_end(scratch); + return result; +} diff --git a/src/eval/eval_bundles.h b/src/eval/eval_bundles.h index c5028e08..9801fbf8 100644 --- a/src/eval/eval_bundles.h +++ b/src/eval/eval_bundles.h @@ -12,18 +12,22 @@ struct E_Eval { E_Value value; E_Space space; - E_ExprChain exprs; + E_Expr *expr; E_IRTreeAndType irtree; String8 bytecode; E_InterpretationCode code; E_MsgList msgs; }; +//////////////////////////////// +//~ rjf: Globals + +read_only global E_Eval e_eval_nil = {zero_struct, zero_struct, &e_expr_nil, {&e_irnode_nil}}; + //////////////////////////////// //~ rjf: Bundled Evaluation Functions internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr); -internal E_Eval e_eval_from_exprs(Arena *arena, E_ExprChain exprs); internal E_Eval e_eval_from_string(Arena *arena, String8 string); internal E_Eval e_eval_from_stringf(Arena *arena, char *fmt, ...); internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval); diff --git a/src/eval/eval_core.h b/src/eval/eval_core.h index 90d45c52..ea79a619 100644 --- a/src/eval/eval_core.h +++ b/src/eval/eval_core.h @@ -268,6 +268,7 @@ struct E_IRTreeAndType { E_IRNode *root; E_TypeKey type_key; + void *user_data; E_Mode mode; E_MsgList msgs; }; @@ -288,7 +289,6 @@ typedef enum E_MemberKind E_MemberKind_VirtualBase, E_MemberKind_NestedType, E_MemberKind_Padding, - E_MemberKind_Query, E_MemberKind_COUNT } E_MemberKind; @@ -357,6 +357,11 @@ struct E_TypeExpandInfo U64 expr_count; }; +#define E_TYPE_IRGEN_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_IRTreeAndType *irtree) +#define E_TYPE_IRGEN_FUNCTION_NAME(name) e_type_irgen__##name +#define E_TYPE_IRGEN_FUNCTION_DEF(name) internal E_TYPE_IRGEN_FUNCTION_SIG(E_TYPE_IRGEN_FUNCTION_NAME(name)) +typedef E_TYPE_IRGEN_FUNCTION_SIG(E_TypeIRGenFunctionType); + #define E_TYPE_ACCESS_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_Expr *expr, E_IRTreeAndType *lhs_irtree) #define E_TYPE_ACCESS_FUNCTION_NAME(name) e_type_access__##name #define E_TYPE_ACCESS_FUNCTION_DEF(name) internal E_TYPE_ACCESS_FUNCTION_SIG(E_TYPE_ACCESS_FUNCTION_NAME(name)) @@ -382,6 +387,15 @@ typedef E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_SIG(E_TypeExpandIDFromNumFunctionType #define E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(name) internal E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_SIG(E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(name)) typedef E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_SIG(E_TypeExpandNumFromIDFunctionType); +typedef struct E_TypeExpandRule E_TypeExpandRule; +struct E_TypeExpandRule +{ + E_TypeExpandInfoFunctionType *info; + E_TypeExpandRangeFunctionType *range; + E_TypeExpandIDFromNumFunctionType *id_from_num; + E_TypeExpandNumFromIDFunctionType *num_from_id; +}; + typedef struct E_Type E_Type; struct E_Type { @@ -399,11 +413,9 @@ struct E_Type E_Member *members; E_EnumVal *enum_vals; E_Expr **args; + E_TypeIRGenFunctionType *irgen; E_TypeAccessFunctionType *access; - E_TypeExpandInfoFunctionType *expand_info; - E_TypeExpandRangeFunctionType *expand_range; - E_TypeExpandIDFromNumFunctionType *expand_id_from_num; - E_TypeExpandNumFromIDFunctionType *expand_num_from_id; + E_TypeExpandRule expand; }; //////////////////////////////// @@ -483,6 +495,8 @@ struct E_String2ExprMap //////////////////////////////// //~ rjf: Member/Index Lookup Hooks +#if 0 // TODO(rjf): @eval + typedef struct E_LookupInfo E_LookupInfo; struct E_LookupInfo { @@ -565,10 +579,12 @@ struct E_LookupRuleExprPair E_LookupRule *rule; E_Expr *expr; }; +#endif //////////////////////////////// //~ rjf: IR Generation Hooks +#if 0 // TODO(rjf): @eval #define E_IRGEN_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_Expr *expr) #define E_IRGEN_FUNCTION_NAME(name) e_irgen_##name #define E_IRGEN_FUNCTION_DEF(name) internal E_IRGEN_FUNCTION_SIG(E_IRGEN_FUNCTION_NAME(name)) @@ -602,6 +618,7 @@ struct E_IRGenRuleMap U64 slots_count; E_IRGenRuleSlot *slots; }; +#endif //////////////////////////////// //~ rjf: Type Pattern -> Hook Key Data Structure (Auto View Rules) diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 8d67064b..03cb1a7f 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -103,268 +103,10 @@ e_select_ir_ctx(E_IRCtx *ctx) } } -//////////////////////////////// -//~ rjf: File System Lookup Rules - -typedef struct E_FolderAccel E_FolderAccel; -struct E_FolderAccel -{ - String8 folder_path; - String8Array folders; - String8Array files; -}; - -E_LOOKUP_INFO_FUNCTION_DEF(folder) -{ - E_LookupInfo info = {0}; - { - Temp scratch = scratch_begin(&arena, 1); - - //- rjf: evaluate lhs file path ID - E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs->root); - String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); - E_Interpretation lhs_interp = e_interpret(lhs_bytecode); - E_Value lhs_value = lhs_interp.value; - U64 lhs_string_id = lhs_value.u64; - String8 folder_path = e_string_from_id(lhs_string_id); - - //- rjf: compute filter - omit common prefixes (common parent paths) - String8 local_filter = filter; - { - U64 folder_pos_in_filter = str8_find_needle(filter, 0, folder_path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); - if(folder_pos_in_filter < filter.size) - { - local_filter = str8_skip(local_filter, folder_pos_in_filter+folder_path.size); - local_filter = str8_skip_chop_slashes(local_filter); - } - else - { - MemoryZeroStruct(&local_filter); - } - } - - //- rjf: gather & filter files in this folder - String8List folder_paths = {0}; - String8List file_paths = {0}; - { - OS_FileIter *iter = os_file_iter_begin(scratch.arena, folder_path, 0); - for(OS_FileInfo info = {0}; os_file_iter_next(scratch.arena, iter, &info);) - { - FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, local_filter, info.name); - if(matches.count == matches.needle_part_count) - { - if(info.props.flags & FilePropertyFlag_IsFolder) - { - str8_list_push(scratch.arena, &folder_paths, push_str8_copy(arena, info.name)); - } - else - { - str8_list_push(scratch.arena, &file_paths, push_str8_copy(arena, info.name)); - } - } - } - os_file_iter_end(iter); - } - - //- rjf: build accelerator - E_FolderAccel *accel = push_array(arena, E_FolderAccel, 1); - accel->folder_path = push_str8_copy(arena, folder_path); - accel->folders = str8_array_from_list(arena, &folder_paths); - accel->files = str8_array_from_list(arena, &file_paths); - info.user_data = accel; - info.idxed_expr_count = accel->folders.count + accel->files.count; - scratch_end(scratch); - } - return info; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(folder) -{ - E_FolderAccel *accel = (E_FolderAccel *)user_data; - U64 out_idx = 0; - for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) - { - Temp scratch = scratch_begin(&arena, 1); - E_Expr *expr = &e_expr_nil; - String8 expr_string = {0}; - if(0 <= idx && idx < accel->folders.count) - { - String8 folder_name = accel->folders.v[idx - 0]; - String8 folder_path = push_str8f(scratch.arena, "%S%s%S", accel->folder_path, accel->folder_path.size != 0 ? "/" : "", folder_name); - expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); - expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("folder")); - expr->space = e_space_make(E_SpaceKind_FileSystem); - expr->value.u64 = e_id_from_string(folder_path); - expr_string = push_str8f(arena, "\"%S\"", escaped_from_raw_str8(scratch.arena, folder_name)); - } - else if(accel->folders.count <= idx && idx < accel->folders.count + accel->files.count) - { - String8 file_name = accel->files.v[idx - accel->folders.count]; - String8 file_path = push_str8f(scratch.arena, "%S%s%S", accel->folder_path, accel->folder_path.size != 0 ? "/" : "", file_name); - expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); - expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("file")); - expr->space = e_space_make(E_SpaceKind_FileSystem); - expr->value.u64 = e_id_from_string(file_path); - expr_string = push_str8f(arena, "\"%S\"", escaped_from_raw_str8(scratch.arena, file_name)); - } - exprs[out_idx] = expr; - exprs_strings[out_idx] = expr_string; - scratch_end(scratch); - } -} - -E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(folder) -{ - U64 id = 0; - E_FolderAccel *accel = (E_FolderAccel *)user_data; - String8 name = {0}; - if(0 < num && num <= accel->folders.count) - { - name = accel->folders.v[num-1]; - } - else if(accel->folders.count < num && num <= accel->folders.count+accel->files.count) - { - name = accel->files.v[num-accel->folders.count-1]; - } - id = e_hash_from_string(5381, name); - return id; -} - -E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(folder) -{ - U64 num = 0; - E_FolderAccel *accel = (E_FolderAccel *)user_data; - for(U64 idx = 0; idx < accel->folders.count+accel->files.count; idx += 1) - { - String8 name = {0}; - if(0 <= idx && idx < accel->folders.count) - { - name = accel->folders.v[idx]; - } - else if(accel->folders.count <= idx && idx < accel->folders.count+accel->files.count) - { - name = accel->files.v[idx-accel->folders.count]; - } - U64 hash = e_hash_from_string(5381, name); - if(hash == id) - { - num = idx+1; - break; - } - } - return num; -} - -typedef struct E_FileAccel E_FileAccel; -struct E_FileAccel -{ - String8 file_path; - FileProperties props; - String8Array fields; -}; - -E_LOOKUP_INFO_FUNCTION_DEF(file) -{ - E_FileAccel *accel = push_array(arena, E_FileAccel, 1); - { - Temp scratch = scratch_begin(&arena, 1); - - //- rjf: evaluate lhs file path ID - E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs->root); - String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); - E_Interpretation lhs_interp = e_interpret(lhs_bytecode); - E_Value lhs_value = lhs_interp.value; - U64 lhs_string_id = lhs_value.u64; - - //- rjf: get file path - String8 file_path = e_string_from_id(lhs_string_id); - - //- rjf: build field list - String8List fields = {0}; - str8_list_pushf(arena, &fields, "size"); - str8_list_pushf(arena, &fields, "last_modified_time"); - str8_list_pushf(arena, &fields, "creation_time"); - str8_list_pushf(arena, &fields, "data"); - - //- rjf: fill accel - accel->file_path = push_str8_copy(arena, file_path); - accel->props = os_properties_from_file_path(file_path); - accel->fields = str8_array_from_list(arena, &fields); - - scratch_end(scratch); - } - E_LookupInfo info = {accel, accel->fields.count}; - return info; -} - -E_LOOKUP_ACCESS_FUNCTION_DEF(file) -{ - E_LookupAccess result = {{&e_irnode_nil}}; - if(kind == E_ExprKind_MemberAccess) - { - E_FileAccel *accel = (E_FileAccel *)user_data; - String8 member_name = rhs->string; - if(str8_match(member_name, str8_lit("size"), 0)) - { - E_Space space = e_space_make(E_SpaceKind_FileSystem); - space.u64_0 = e_id_from_string(accel->file_path); - result.irtree_and_type.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.size)); - result.irtree_and_type.type_key = e_type_key_basic(E_TypeKind_U64); - result.irtree_and_type.mode = E_Mode_Value; - } - else if(str8_match(member_name, str8_lit("last_modified_time"), 0)) - { - E_Space space = e_space_make(E_SpaceKind_FileSystem); - space.u64_0 = e_id_from_string(accel->file_path); - result.irtree_and_type.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.modified)); - result.irtree_and_type.type_key = e_type_key_basic(E_TypeKind_U64); - result.irtree_and_type.mode = E_Mode_Value; - } - else if(str8_match(member_name, str8_lit("creation_time"), 0)) - { - E_Space space = e_space_make(E_SpaceKind_FileSystem); - space.u64_0 = e_id_from_string(accel->file_path); - result.irtree_and_type.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.created)); - result.irtree_and_type.type_key = e_type_key_basic(E_TypeKind_U64); - result.irtree_and_type.mode = E_Mode_Value; - } - else if(str8_match(member_name, str8_lit("data"), 0)) - { - E_Space space = e_space_make(E_SpaceKind_File); - space.u64_0 = e_id_from_string(accel->file_path); - result.irtree_and_type.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); - result.irtree_and_type.type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), accel->props.size, 0); - result.irtree_and_type.mode = E_Mode_Offset; - } - } - return result; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(file) -{ - E_FileAccel *accel = (E_FileAccel *)user_data; - U64 out_idx = 0; - for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) - { - E_Expr *expr = &e_expr_nil; - String8 string = {0}; - if(0 <= idx && idx < accel->fields.count) - { - String8 name = accel->fields.v[idx]; - expr = e_push_expr(arena, E_ExprKind_MemberAccess, 0); - E_Expr *rhs = e_push_expr(arena, E_ExprKind_LeafIdentifier, 0); - rhs->string = push_str8_copy(arena, name); - e_expr_push_child(expr, e_expr_ref(arena, lhs)); - e_expr_push_child(expr, rhs); - } - exprs[out_idx] = expr; - exprs_strings[out_idx] = string; - } -} - //////////////////////////////// //~ rjf: Slice Lookup Rules +#if 0 // TODO(rjf): @eval typedef struct E_SliceAccel E_SliceAccel; struct E_SliceAccel { @@ -529,55 +271,6 @@ E_LOOKUP_RANGE_FUNCTION_DEF(slice) } } -E_LOOKUP_INFO_FUNCTION_DEF(default) -{ - E_LookupInfo lookup_info = {0}; - { - E_TypeKey lhs_type_key = e_type_unwrap(lhs->type_key); - E_TypeKind lhs_type_kind = e_type_kind_from_key(lhs_type_key); - if(e_type_kind_is_pointer_or_ref(lhs_type_kind)) - { - E_Type *type = e_type_from_key__cached(lhs_type_key); - lookup_info.idxed_expr_count = type->count; - if(type->count == 1) - { - E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(lhs->type_key)); - E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - if(direct_type_kind == E_TypeKind_Struct || - direct_type_kind == E_TypeKind_Class || - direct_type_kind == E_TypeKind_Union) - { - E_MemberArray data_members = e_type_data_members_from_key_filter__cached(direct_type_key, filter); - lookup_info.named_expr_count = data_members.count; - } - else if(direct_type_kind == E_TypeKind_Enum) - { - E_Type *direct_type = e_type_from_key__cached(direct_type_key); - lookup_info.named_expr_count = direct_type->count; - } - } - } - else if(lhs_type_kind == E_TypeKind_Struct || - lhs_type_kind == E_TypeKind_Class || - lhs_type_kind == E_TypeKind_Union) - { - E_MemberArray data_members = e_type_data_members_from_key_filter__cached(lhs_type_key, filter); - lookup_info.named_expr_count = data_members.count; - } - else if(lhs_type_kind == E_TypeKind_Enum) - { - E_Type *direct_type = e_type_from_key__cached(lhs_type_key); - lookup_info.named_expr_count = direct_type->count; - } - else if(lhs_type_kind == E_TypeKind_Array) - { - E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); - lookup_info.idxed_expr_count = lhs_type->count; - } - } - return lookup_info; -} - E_LOOKUP_ACCESS_FUNCTION_DEF(default) { // @@ -619,7 +312,6 @@ E_LOOKUP_ACCESS_FUNCTION_DEF(default) B32 r_found = 0; E_TypeKey r_type = zero_struct; U64 r_value = 0; - String8 r_query_name = {0}; B32 r_is_constant_value = 0; { Temp scratch = scratch_begin(&arena, 1); @@ -631,10 +323,6 @@ E_LOOKUP_ACCESS_FUNCTION_DEF(default) r_type = match.type_key; r_value = match.off; } - if(match.kind == E_MemberKind_Query) - { - r_query_name = exprr->string; - } if(match.kind == E_MemberKind_Null) { E_Type *type = e_type_from_key__cached(check_type_key); @@ -825,111 +513,6 @@ E_LOOKUP_ACCESS_FUNCTION_DEF(default) return result; } -E_LOOKUP_RANGE_FUNCTION_DEF(default) -{ - Temp scratch = scratch_begin(&arena, 1); - { - //- rjf: unpack type of expression - E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(scratch.arena, lhs); - E_TypeKey lhs_type_key = lhs_irtree.type_key; - E_TypeKind lhs_type_kind = e_type_kind_from_key(lhs_type_key); - E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(lhs_type_key)); - E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); - - //- rjf: pull out specific kinds of types - B32 do_struct_range = 0; - B32 do_enum_range = 0; - B32 do_index_range = 0; - E_TypeKey enum_type_key = zero_struct; - E_TypeKey struct_type_key = zero_struct; - E_TypeKind struct_type_kind = E_TypeKind_Null; - if(e_type_kind_is_pointer_or_ref(lhs_type_kind)) - { - E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); - if(lhs_type->count == 1 && - (direct_type_kind == E_TypeKind_Struct || - direct_type_kind == E_TypeKind_Union || - direct_type_kind == E_TypeKind_Class)) - { - struct_type_key = direct_type_key; - struct_type_kind = direct_type_kind; - do_struct_range = 1; - } - else if(lhs_type->count == 1 && direct_type_kind == E_TypeKind_Enum) - { - do_enum_range = 1; - enum_type_key = direct_type_key; - } - else - { - do_index_range = 1; - } - } - else if(lhs_type_kind == E_TypeKind_Struct || - lhs_type_kind == E_TypeKind_Union || - lhs_type_kind == E_TypeKind_Class) - { - struct_type_key = lhs_type_key; - struct_type_kind = lhs_type_kind; - do_struct_range = 1; - } - else if(lhs_type_kind == E_TypeKind_Enum) - { - enum_type_key = lhs_type_key; - do_enum_range = 1; - } - else if(lhs_type_kind == E_TypeKind_Set) - { - do_index_range = 1; - } - else if(lhs_type_kind == E_TypeKind_Array) - { - do_index_range = 1; - } - - //- rjf: struct case -> the lookup-range will return a range of members - if(do_struct_range) - { - E_MemberArray data_members = e_type_data_members_from_key_filter__cached(struct_type_key, filter); - Rng1U64 legal_idx_range = r1u64(0, data_members.count); - Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); - U64 read_range_count = dim_1u64(read_range); - for(U64 idx = 0; idx < read_range_count; idx += 1) - { - U64 member_idx = idx + read_range.min; - String8 member_name = data_members.v[member_idx].name; - exprs[idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, member_name); - } - } - - //- rjf: enum case -> the lookup-range will return a range of enum constants - else if(do_enum_range) - { - E_Type *type = e_type_from_key__cached(enum_type_key); - Rng1U64 legal_idx_range = r1u64(0, type->count); - Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); - U64 read_range_count = dim_1u64(read_range); - for(U64 idx = 0; idx < read_range_count; idx += 1) - { - U64 member_idx = idx + read_range.min; - String8 member_name = type->enum_vals[member_idx].name; - exprs[idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, member_name); - } - } - - //- rjf: ptr case -> the lookup-range will return a range of dereferences - else if(do_index_range) - { - U64 read_range_count = dim_1u64(idx_range); - for(U64 idx = 0; idx < read_range_count; idx += 1) - { - exprs[idx] = e_expr_irext_array_index(arena, lhs, &lhs_irtree, idx_range.min + idx); - } - } - } - scratch_end(scratch); -} - E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(default) { return num; @@ -939,10 +522,12 @@ E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(default) { return id; } +#endif //////////////////////////////// //~ rjf: Member Filtering Lookup Rules +#if 0 // TODO(rjf): @eval typedef struct E_MemberFilterAccel E_MemberFilterAccel; struct E_MemberFilterAccel { @@ -1112,10 +697,12 @@ E_LOOKUP_RANGE_FUNCTION_DEF(only_and_omit) scratch_end(scratch); } } +#endif //////////////////////////////// //~ rjf: Lookups +#if 0 // TODO(rjf): @eval internal E_LookupRuleMap e_lookup_rule_map_make(Arena *arena, U64 slots_count) { @@ -1185,10 +772,12 @@ e_lookup_rule_from_string(String8 string) } return result; } +#endif //////////////////////////////// //~ rjf: IR Gen Rules +#if 0 // TODO(rjf): @eval E_IRGEN_FUNCTION_DEF(bswap) { E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr); @@ -1252,6 +841,7 @@ e_irgen_rule_from_string(String8 string) } return rule; } +#endif //////////////////////////////// //~ rjf: Auto Hooks @@ -1838,10 +1428,6 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) r_type = match.type_key; r_value = match.off; } - if(match.kind == E_MemberKind_Query) - { - r_query_name = exprr->string; - } if(match.kind == E_MemberKind_Null) { E_Type *type = e_type_from_key__cached(check_type_key); @@ -2034,1261 +1620,1268 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) //- rjf: top-level irtree/type extraction -E_IRGEN_FUNCTION_DEF(default) -{ - E_IRTreeAndType result = {&e_irnode_nil}; - E_ExprKind kind = expr->kind; - switch(kind) - { - default:{}break; - - //- rjf: accesses - case E_ExprKind_MemberAccess: - case E_ExprKind_ArrayIndex: - { - // rjf: unpack left-hand-size - E_Expr *lhs = expr->first; - E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); - - // 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); - }break; - - //- rjf: dereference - case E_ExprKind_Deref: - { - // rjf: unpack operand - E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - E_TypeKey r_type = e_type_unwrap(r_tree.type_key); - E_TypeKind r_type_kind = e_type_kind_from_key(r_type); - E_TypeKey r_type_direct = e_type_direct_from_key(r_type); - U64 r_type_direct_size = e_type_byte_size_from_key(r_type_direct); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - - // rjf: bad conditions? -> error if applicable, exit - if(r_tree.root->op == 0) - { - break; - } - else if(r_type_direct_size == 0 && - (r_type_kind == E_TypeKind_Ptr || - r_type_kind == E_TypeKind_LRef || - r_type_kind == E_TypeKind_RRef)) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->location, "Cannot dereference pointers of zero-sized types."); - break; - } - else if(r_type_direct_size == 0 && r_type_kind == E_TypeKind_Array) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->location, "Cannot dereference arrays of zero-sized types."); - break; - } - else if(r_type_kind != E_TypeKind_Array && - r_type_kind != E_TypeKind_Ptr && - r_type_kind != E_TypeKind_LRef && - r_type_kind != E_TypeKind_RRef) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->location, "Cannot dereference this type."); - break; - } - - // rjf: generate - { - E_IRNode *new_tree = r_tree.root; - if(r_tree.mode != E_Mode_Value && - (r_type_kind == E_TypeKind_Ptr || - r_type_kind == E_TypeKind_LRef || - r_type_kind == E_TypeKind_RRef)) - { - new_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); - } - result.root = new_tree; - result.type_key = r_type_direct; - result.mode = E_Mode_Offset; - } - }break; - - //- rjf: address-of - case E_ExprKind_Address: - { - // rjf: unpack operand - E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - E_TypeKey r_type = r_tree.type_key; - E_TypeKey r_type_unwrapped = e_type_unwrap(r_type); - E_TypeKind r_type_unwrapped_kind = e_type_kind_from_key(r_type_unwrapped); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - - // rjf: bad conditions? -> error if applicable, exit - if(r_tree.root->op == 0) - { - break; - } - else if(e_type_key_match(e_type_key_zero(), r_type_unwrapped)) - { - break; - } - - // rjf: generate - result.root = r_tree.root; - result.type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, r_type_unwrapped, 1, 0); - result.mode = E_Mode_Value; - }break; - - //- rjf: cast - case E_ExprKind_Cast: - { - // rjf: unpack operands - E_Expr *cast_type_expr = expr->first; - E_Expr *casted_expr = cast_type_expr->next; - E_TypeKey cast_type = e_type_from_expr(cast_type_expr); - E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type); - U64 cast_type_byte_size = e_type_byte_size_from_key(cast_type); - E_IRTreeAndType casted_tree = e_irtree_and_type_from_expr(arena, casted_expr); - e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs); - E_TypeKey casted_type = e_type_unwrap(casted_tree.type_key); - E_TypeKind casted_type_kind = e_type_kind_from_key(casted_type); - U64 casted_type_byte_size = e_type_byte_size_from_key(casted_type); - U8 in_group = e_type_group_from_kind(casted_type_kind); - U8 out_group = e_type_group_from_kind(cast_type_kind); - RDI_EvalConversionKind conversion_rule = rdi_eval_conversion_kind_from_typegroups(in_group, out_group); - - // rjf: bad conditions? -> error if applicable, exit - if(casted_tree.root->op == 0) - { - break; - } - else if(cast_type_kind == E_TypeKind_Null) - { - break; - } - else if(conversion_rule != RDI_EvalConversionKind_Noop && - conversion_rule != RDI_EvalConversionKind_Legal) - { - String8 text = str8_lit("Unknown cast conversion rule."); - if(conversion_rule < RDI_EvalConversionKind_COUNT) - { - text.str = rdi_explanation_string_from_eval_conversion_kind(conversion_rule, &text.size); - } - e_msg(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, text); - break; - } - - // rjf: generate - { - E_IRNode *in_tree = e_irtree_resolve_to_value(arena, casted_tree.mode, casted_tree.root, casted_type); - E_IRNode *new_tree = in_tree; - if(conversion_rule == RDI_EvalConversionKind_Legal) - { - new_tree = e_irtree_convert_lo(arena, in_tree, out_group, in_group); - } - if(cast_type_byte_size < casted_type_byte_size && e_type_kind_is_integer(cast_type_kind)) - { - new_tree = e_irtree_trunc(arena, in_tree, cast_type); - } - result.root = new_tree; - result.type_key = cast_type; - result.mode = E_Mode_Value; - } - }break; - - //- rjf: sizeof - case E_ExprKind_Sizeof: - { - // rjf: unpack operand - E_Expr *r_expr = expr->first; - E_TypeKey r_type = zero_struct; - E_Space space = r_expr->space; - switch(r_expr->kind) - { - case E_ExprKind_TypeIdent: - case E_ExprKind_Ptr: - case E_ExprKind_Array: - case E_ExprKind_Func: - { - r_type = e_type_from_expr(r_expr); - }break; - default: - { - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - r_type = r_tree.type_key; - }break; - } - - // rjf: bad conditions? -> error if applicable, exit - if(e_type_key_match(r_type, e_type_key_zero())) - { - break; - } - else if(e_type_kind_from_key(r_type) == E_TypeKind_Null) - { - break; - } - - // rjf: generate - { - U64 r_type_byte_size = e_type_byte_size_from_key(r_type); - result.root = e_irtree_const_u(arena, r_type_byte_size); - result.type_key = e_type_key_basic(E_TypeKind_U64); - result.mode = E_Mode_Value; - } - }break; - - //- rjf: typeof - case E_ExprKind_Typeof: - { - // rjf: evaluate operand tree - E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - - // rjf: fill output - result.root = e_irtree_const_u(arena, 0); - result.type_key = r_tree.type_key; - result.mode = E_Mode_Null; - }break; - - //- rjf: byteswap - case E_ExprKind_ByteSwap: - { - // rjf: unpack operand - E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - E_TypeKey r_type = e_type_unwrap(r_tree.type_key); - E_TypeKind r_type_kind = e_type_kind_from_key(r_type); - U64 r_type_size = e_type_byte_size_from_key(r_type); - - // rjf: bad conditions? -> error if applicable, exit - if(!e_type_kind_is_integer(r_type_kind) || (r_type_size != 8 && r_type_size != 4 && r_type_size != 2)) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Byteswapping this type is not supported."); - break; - } - - // rjf: generate - { - E_IRNode *node = e_push_irnode(arena, RDI_EvalOp_ByteSwap); - E_IRNode *rhs = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); - e_irnode_push_child(node, rhs); - node->value.u64 = r_type_size; - result.root = node; - result.mode = E_Mode_Value; - result.type_key = r_type; - } - }break; - - //- rjf: unary operations - case E_ExprKind_Pos: - { - result = e_irtree_and_type_from_expr(arena, expr->first); - }break; - case E_ExprKind_Neg: - case E_ExprKind_BitNot: - { - // rjf: unpack operand - E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - E_TypeKey r_type = e_type_unwrap(r_tree.type_key); - E_TypeKind r_type_kind = e_type_kind_from_key(r_type); - RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); - E_TypeKey r_type_promoted = e_type_promote(r_type); - RDI_EvalOp op = e_opcode_from_expr_kind(kind); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - - // rjf: bad conditions? -> error if applicable, exit - if(r_tree.root->op == 0) - { - break; - } - else if(!rdi_eval_op_typegroup_are_compatible(op, r_type_group)) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Cannot use this operator on this type."); - break; - } - - // rjf: generate - { - E_IRNode *in_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); - in_tree = e_irtree_convert_hi(arena, in_tree, r_type_promoted, r_type); - E_IRNode *new_tree = e_irtree_unary_op(arena, op, r_type_group, in_tree); - result.root = new_tree; - result.type_key = r_type_promoted; - result.mode = E_Mode_Value; - } - }break; - case E_ExprKind_LogNot: - { - // rjf: unpack operand - E_Expr *r_expr = expr->first; - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - E_TypeKey r_type = e_type_unwrap(r_tree.type_key); - E_TypeKind r_type_kind = e_type_kind_from_key(r_type); - RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); - E_TypeKey r_type_promoted = e_type_key_basic(E_TypeKind_Bool); - RDI_EvalOp op = e_opcode_from_expr_kind(kind); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - - // rjf: bad conditions? -> error if applicable, exit - if(r_tree.root->op == 0) - { - break; - } - else if(!rdi_eval_op_typegroup_are_compatible(op, r_type_group)) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Cannot use this operator on this type."); - break; - } - - // rjf: generate - { - E_IRNode *in_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); - in_tree = e_irtree_convert_hi(arena, in_tree, r_type_promoted, r_type); - E_IRNode *new_tree = e_irtree_unary_op(arena, op, r_type_group, in_tree); - result.root = new_tree; - result.type_key = r_type_promoted; - result.mode = E_Mode_Value; - } - }break; - - //- rjf: binary operations - case E_ExprKind_Mul: - case E_ExprKind_Div: - case E_ExprKind_Mod: - case E_ExprKind_Add: - case E_ExprKind_Sub: - case E_ExprKind_LShift: - case E_ExprKind_RShift: - case E_ExprKind_Less: - case E_ExprKind_LsEq: - case E_ExprKind_Grtr: - case E_ExprKind_GrEq: - case E_ExprKind_EqEq: - case E_ExprKind_NtEq: - case E_ExprKind_BitAnd: - case E_ExprKind_BitXor: - case E_ExprKind_BitOr: - case E_ExprKind_LogAnd: - case E_ExprKind_LogOr: - { - // rjf: unpack operands - RDI_EvalOp op = e_opcode_from_expr_kind(kind); - B32 is_comparison = e_expr_kind_is_comparison(kind); - E_Expr *l_expr = expr->first; - E_Expr *r_expr = l_expr->next; - E_IRTreeAndType l_tree = e_irtree_and_type_from_expr(arena, l_expr); - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - E_TypeKey l_type = e_type_unwrap_enum(e_type_unwrap(l_tree.type_key)); - E_TypeKey r_type = e_type_unwrap_enum(e_type_unwrap(r_tree.type_key)); - E_TypeKind l_type_kind = e_type_kind_from_key(l_type); - E_TypeKind r_type_kind = e_type_kind_from_key(r_type); - if(l_type.kind == E_TypeKeyKind_Reg) - { - l_type_kind = E_TypeKind_U64; - l_type = e_type_key_basic(l_type_kind); - } - if(r_type.kind == E_TypeKeyKind_Reg) - { - r_type_kind = E_TypeKind_U64; - r_type = e_type_key_basic(r_type_kind); - } - B32 l_is_pointer = (l_type_kind == E_TypeKind_Ptr); - B32 l_is_decay = (l_type_kind == E_TypeKind_Array && l_tree.mode == E_Mode_Offset); - B32 l_is_pointer_like = (l_is_pointer || l_is_decay); - B32 r_is_pointer = (r_type_kind == E_TypeKind_Ptr); - B32 r_is_decay = (r_type_kind == E_TypeKind_Array && r_tree.mode == E_Mode_Offset); - B32 r_is_pointer_like = (r_is_pointer || r_is_decay); - RDI_EvalTypeGroup l_type_group = e_type_group_from_kind(l_type_kind); - RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); - - // rjf: bad conditions? -> error if applicable, exit - if(l_tree.root->op == 0 || r_tree.root->op == 0) - { - break; - } - - // rjf: determine arithmetic path -#define E_ArithPath_Normal 0 -#define E_ArithPath_PtrAdd 1 -#define E_ArithPath_PtrSub 2 -#define E_ArithPath_PtrArrayCompare 3 - B32 ptr_arithmetic_mul_rptr = 0; - U32 arith_path = E_ArithPath_Normal; - if(kind == E_ExprKind_Add) - { - if(l_is_pointer_like && e_type_kind_is_integer(r_type_kind)) - { - arith_path = E_ArithPath_PtrAdd; - } - if(l_is_pointer_like && e_type_kind_is_integer(l_type_kind)) - { - arith_path = E_ArithPath_PtrAdd; - ptr_arithmetic_mul_rptr = 1; - } - } - else if(kind == E_ExprKind_Sub) - { - if(l_is_pointer_like && e_type_kind_is_integer(r_type_kind)) - { - arith_path = E_ArithPath_PtrAdd; - } - if(l_is_pointer_like && r_is_pointer_like) - { - E_TypeKey l_type_direct = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(l_type))); - E_TypeKey r_type_direct = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(r_type))); - U64 l_type_direct_byte_size = e_type_byte_size_from_key(l_type_direct); - U64 r_type_direct_byte_size = e_type_byte_size_from_key(r_type_direct); - if(l_type_direct_byte_size == r_type_direct_byte_size) - { - arith_path = E_ArithPath_PtrSub; - } - } - } - else if(kind == E_ExprKind_EqEq) - { - if(l_type_kind == E_TypeKind_Array && (r_type_kind == E_TypeKind_Ptr || r_is_decay)) - { - arith_path = E_ArithPath_PtrArrayCompare; - } - if(r_type_kind == E_TypeKind_Array && (l_type_kind == E_TypeKind_Ptr || l_is_decay)) - { - arith_path = E_ArithPath_PtrArrayCompare; - } - } - - // rjf: generate according to arithmetic path - switch(arith_path) - { - //- rjf: normal arithmetic - case E_ArithPath_Normal: - { - // rjf: bad conditions? -> error if applicable, exit - if(!rdi_eval_op_typegroup_are_compatible(op, l_type_group) || - !rdi_eval_op_typegroup_are_compatible(op, r_type_group)) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Cannot use this operator on this type."); - break; - } - - // rjf: generate - { - E_TypeKey final_type_key = is_comparison ? e_type_key_basic(E_TypeKind_Bool) : l_type; - E_IRNode *l_value_tree = e_irtree_resolve_to_value(arena, l_tree.mode, l_tree.root, l_type); - E_IRNode *r_value_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); - l_value_tree = e_irtree_convert_hi(arena, l_value_tree, l_type, l_type); - r_value_tree = e_irtree_convert_hi(arena, r_value_tree, l_type, r_type); - E_IRNode *new_tree = e_irtree_binary_op(arena, op, l_type_group, l_value_tree, r_value_tree); - result.root = new_tree; - result.type_key = final_type_key; - result.mode = E_Mode_Value; - } - }break; - - //- rjf: pointer addition - case E_ArithPath_PtrAdd: - { - // rjf: map l/r to ptr/int - E_IRTreeAndType *ptr_tree = &l_tree; - E_IRTreeAndType *int_tree = &r_tree; - B32 ptr_is_decay = l_is_decay; - if(ptr_arithmetic_mul_rptr) - { - ptr_tree = &r_tree; - int_tree = &l_tree; - ptr_is_decay = r_is_decay; - } - - // rjf: unpack type - E_TypeKey direct_type = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(ptr_tree->type_key))); - U64 direct_type_size = e_type_byte_size_from_key(direct_type); - - // rjf: generate - { - E_IRNode *ptr_root = ptr_tree->root; - if(!ptr_is_decay) - { - ptr_root = e_irtree_resolve_to_value(arena, ptr_tree->mode, ptr_root, ptr_tree->type_key); - } - E_IRNode *int_root = int_tree->root; - int_root = e_irtree_resolve_to_value(arena, int_tree->mode, int_root, int_tree->type_key); - if(direct_type_size > 1) - { - E_IRNode *const_root = e_irtree_const_u(arena, direct_type_size); - int_root = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, int_root, const_root); - } - E_TypeKey ptr_type = ptr_tree->type_key; - if(ptr_is_decay) - { - ptr_type = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, direct_type, 1, 0); - } - E_IRNode *new_root = e_irtree_binary_op_u(arena, op, ptr_root, int_root); - result.root = new_root; - result.type_key = ptr_type; - result.mode = E_Mode_Value; - } - }break; - - //- rjf: pointer subtraction - case E_ArithPath_PtrSub: - { - // rjf: unpack type - E_TypeKey direct_type = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(l_type))); - U64 direct_type_size = e_type_byte_size_from_key(direct_type); - - // rjf: generate - E_IRNode *l_root = l_tree.root; - E_IRNode *r_root = r_tree.root; - if(!l_is_decay) - { - l_root = e_irtree_resolve_to_value(arena, l_tree.mode, l_root, l_type); - } - if(!r_is_decay) - { - r_root = e_irtree_resolve_to_value(arena, r_tree.mode, r_root, r_type); - } - E_IRNode *op_tree = e_irtree_binary_op_u(arena, op, l_root, r_root); - E_IRNode *new_tree = op_tree; - if(direct_type_size > 1) - { - E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); - new_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Div, new_tree, const_tree); - } - result.root = new_tree; - result.type_key = e_type_key_basic(E_TypeKind_U64); - result.mode = E_Mode_Value; - }break; - - //- rjf: pointer array comparison - case E_ArithPath_PtrArrayCompare: - { - // rjf: map l/r to pointer/array - B32 ptr_is_decay = l_is_decay; - E_IRTreeAndType *ptr_tree = &l_tree; - E_IRTreeAndType *arr_tree = &r_tree; - if(l_type_kind == E_TypeKind_Array && l_tree.mode == E_Mode_Value) - { - ptr_is_decay = r_is_decay; - ptr_tree = &r_tree; - arr_tree = &l_tree; - } - - // rjf: resolve pointer to value, sized same as array - E_IRNode *ptr_root = ptr_tree->root; - E_IRNode *arr_root = arr_tree->root; - if(!ptr_is_decay) - { - ptr_root = e_irtree_resolve_to_value(arena, ptr_tree->mode, ptr_tree->root, ptr_tree->type_key); - } - - // rjf: read from pointer into value, to compare with array - E_IRNode *mem_root = e_irtree_mem_read_type(arena, ptr_root, arr_tree->type_key); - - // rjf: generate - result.root = e_irtree_binary_op(arena, op, RDI_EvalTypeGroup_Other, mem_root, arr_root); - result.type_key = e_type_key_basic(E_TypeKind_Bool); - result.mode = E_Mode_Value; - }break; - } - }break; - - //- rjf: ternary operators - case E_ExprKind_Ternary: - { - // rjf: unpack operands - E_Expr *c_expr = expr->first; - E_Expr *l_expr = c_expr->next; - E_Expr *r_expr = l_expr->next; - E_IRTreeAndType c_tree = e_irtree_and_type_from_expr(arena, c_expr); - E_IRTreeAndType l_tree = e_irtree_and_type_from_expr(arena, l_expr); - E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); - e_msg_list_concat_in_place(&result.msgs, &c_tree.msgs); - e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs); - e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); - E_TypeKey c_type = e_type_unwrap(c_tree.type_key); - E_TypeKey l_type = e_type_unwrap(l_tree.type_key); - E_TypeKey r_type = e_type_unwrap(r_tree.type_key); - E_TypeKind c_type_kind = e_type_kind_from_key(c_type); - E_TypeKind l_type_kind = e_type_kind_from_key(l_type); - E_TypeKind r_type_kind = e_type_kind_from_key(r_type); - E_TypeKey result_type = l_type; - - // rjf: bad conditions? -> error if applicable, exit - if(c_tree.root->op == 0 || l_tree.root->op == 0 || r_tree.root->op == 0) - { - break; - } - else if(!e_type_kind_is_integer(c_type_kind) && c_type_kind != E_TypeKind_Bool) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Conditional term must be an integer or boolean type."); - } - else if(!e_type_match(l_type, r_type)) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Left and right terms must have matching types."); - } - - // rjf: generate - { - E_IRNode *c_value_tree = e_irtree_resolve_to_value(arena, c_tree.mode, c_tree.root, c_type); - E_IRNode *l_value_tree = e_irtree_resolve_to_value(arena, l_tree.mode, l_tree.root, l_type); - E_IRNode *r_value_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); - l_value_tree = e_irtree_convert_hi(arena, l_value_tree, result_type, l_type); - r_value_tree = e_irtree_convert_hi(arena, r_value_tree, result_type, r_type); - E_IRNode *new_tree = e_irtree_conditional(arena, c_value_tree, l_value_tree, r_value_tree); - result.root = new_tree; - result.type_key = result_type; - result.mode = E_Mode_Value; - } - }break; - - //- rjf: call - case E_ExprKind_Call: - { - E_Expr *lhs = expr->first; - E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); - E_TypeKey lhs_type_key = lhs_irtree.type_key; - E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); - - // 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) - { - Temp scratch = scratch_begin(&arena, 1); - - // rjf: generate result via first argument to lens - result = e_irtree_and_type_from_expr(arena, lhs->next); - - // rjf: count extra arguments - U64 arg_count = 0; - for(E_Expr *arg = lhs->next->next; arg != &e_expr_nil; arg = arg->next) - { - arg_count += 1; - } - - // rjf: flatten extra arguments - E_Expr **args = push_array(scratch.arena, E_Expr *, arg_count); - { - U64 idx = 0; - for(E_Expr *arg = lhs->next->next; arg != &e_expr_nil; arg = arg->next, idx += 1) - { - args[idx] = arg; - } - } - - // rjf: patch resultant type with a lens w/ args, pointing to the original type - result.type_key = e_type_key_cons(.kind = E_TypeKind_Lens, .count = arg_count, .args = args, .direct_key = result.type_key, .name = lhs_type->name); - - scratch_end(scratch); - } - else - { - e_msgf(arena, &result.msgs, E_MsgKind_InterpretationError, expr->location, "Calling this type is not supported."); - } - }break; - - //- rjf: leaf bytecode - case E_ExprKind_LeafBytecode: - { - E_IRNode *new_tree = e_irtree_bytecode_no_copy(arena, expr->bytecode); - new_tree->space = expr->space; - E_TypeKey final_type_key = expr->type_key; - result.root = new_tree; - result.type_key = final_type_key; - result.mode = expr->mode; - }break; - - //- rjf: leaf string literal - case E_ExprKind_LeafStringLiteral: - { - String8 string = expr->string; - E_TypeKey type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_UChar8), string.size, 0); - E_IRNode *new_tree = e_irtree_string_literal(arena, string); - result.root = new_tree; - result.type_key = type_key; - result.mode = E_Mode_Value; - }break; - - //- rjf: leaf U64s - case E_ExprKind_LeafU64: - { - U64 val = expr->value.u64; - E_IRNode *new_tree = e_irtree_const_u(arena, val); - E_TypeKey type_key = zero_struct; - if(0){} - else if(val <= max_S32){type_key = e_type_key_basic(E_TypeKind_S32);} - else if(val <= max_S64){type_key = e_type_key_basic(E_TypeKind_S64);} - else {type_key = e_type_key_basic(E_TypeKind_U64);} - result.root = new_tree; - result.type_key = type_key; - result.mode = E_Mode_Value; - }break; - - //- rjf: leaf F64s - case E_ExprKind_LeafF64: - { - U64 val = expr->value.u64; - E_IRNode *new_tree = e_irtree_const_u(arena, val); - result.root = new_tree; - result.type_key = e_type_key_basic(E_TypeKind_F64); - result.mode = E_Mode_Value; - }break; - - //- rjf: leaf F32s - case E_ExprKind_LeafF32: - { - U32 val = expr->value.u32; - E_IRNode *new_tree = e_irtree_const_u(arena, val); - result.root = new_tree; - result.type_key = e_type_key_basic(E_TypeKind_F32); - result.mode = E_Mode_Value; - }break; - - //- rjf: leaf identifiers - case E_ExprKind_LeafIdentifier: - { - Temp scratch = scratch_begin(&arena, 1); - String8 qualifier = expr->qualifier; - String8 string = expr->string; - String8 string__redirected = string; - B32 string_mapped = 0; - E_TypeKey mapped_type_key = zero_struct; - E_Module *mapped_location_block_module = &e_module_nil; - RDI_LocationBlock *mapped_location_block = 0; - - //- rjf: form namespaceified fallback versions of this lookup string - String8List namespaceified_strings = {0}; - { - E_Module *module = e_ir_state->ctx->primary_module; - RDI_Parsed *rdi = module->rdi; - RDI_Procedure *procedure = e_ir_state->thread_ip_procedure; - U64 name_size = 0; - U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); - String8 containing_procedure_name = str8(name_ptr, name_size); - U64 last_past_scope_resolution_pos = 0; - for(;;) - { - U64 past_next_dbl_colon_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("::"), 0)+2; - U64 past_next_dot_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("."), 0)+1; - U64 past_next_scope_resolution_pos = Min(past_next_dbl_colon_pos, past_next_dot_pos); - if(past_next_scope_resolution_pos >= containing_procedure_name.size) - { - break; - } - String8 new_namespace_prefix_possibility = str8_prefix(containing_procedure_name, past_next_scope_resolution_pos); - String8 namespaceified_string = push_str8f(scratch.arena, "%S%S", new_namespace_prefix_possibility, string); - str8_list_push_front(scratch.arena, &namespaceified_strings, namespaceified_string); - last_past_scope_resolution_pos = past_next_scope_resolution_pos; - } - } - - //- rjf: try to map name as member - if found, string__redirected := "this", and turn - // on later implicit-member-lookup generation - B32 string_is_implicit_member_name = 0; - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("member"), 0))) - { - E_Module *module = e_ir_state->ctx->primary_module; - U32 module_idx = (U32)(module - e_ir_state->ctx->modules); - RDI_Parsed *rdi = module->rdi; - RDI_Procedure *procedure = e_ir_state->thread_ip_procedure; - RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure); - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); - E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module_idx); - E_Member member = e_type_member_from_key_name__cached(container_type_key, string); - if(member.kind != E_MemberKind_Null) - { - string_is_implicit_member_name = 1; - string__redirected = str8_lit("this"); - } - } - - //- rjf: try locals - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("local"), 0))) - { - E_Module *module = e_ir_state->ctx->primary_module; - U32 module_idx = (U32)(module - e_ir_state->ctx->modules); - RDI_Parsed *rdi = module->rdi; - U64 local_num = e_num_from_string(e_ir_state->ctx->locals_map, string__redirected); - if(local_num != 0) - { - RDI_Local *local = rdi_element_from_name_idx(rdi, Locals, local_num-1); - - // rjf: extract local's type key - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, local->type_idx); - mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module_idx); - - // rjf: extract local's location block - U64 ip_voff = e_ir_state->ctx->thread_ip_voff; - for(U32 loc_block_idx = local->location_first; - loc_block_idx < local->location_opl; - loc_block_idx += 1) - { - RDI_LocationBlock *block = rdi_element_from_name_idx(rdi, LocationBlocks, loc_block_idx); - if(block->scope_off_first <= ip_voff && ip_voff < block->scope_off_opl) - { - mapped_location_block_module = module; - mapped_location_block = block; - } - } - } - } - - //- rjf: mapped to location block -> extract or produce bytecode for this mapping - E_Mode mapped_bytecode_mode = E_Mode_Offset; - E_Space mapped_bytecode_space = zero_struct; - String8 mapped_bytecode = {0}; - if(mapped_location_block != 0) - { - E_Module *module = mapped_location_block_module; - E_Space space = module->space; - Arch arch = module->arch; - RDI_Parsed *rdi = module->rdi; - RDI_LocationBlock *block = mapped_location_block; - U64 all_location_data_size = 0; - U8 *all_location_data = rdi_table_from_name(rdi, LocationData, &all_location_data_size); - if(block->location_data_off + sizeof(RDI_LocationKind) <= all_location_data_size) - { - RDI_LocationKind loc_kind = *((RDI_LocationKind *)(all_location_data + block->location_data_off)); - switch(loc_kind) - { - default:{}break; - case RDI_LocationKind_ValBytecodeStream: {mapped_bytecode_mode = E_Mode_Value;}goto bytecode_stream; - case RDI_LocationKind_AddrBytecodeStream:{mapped_bytecode_mode = E_Mode_Offset;}goto bytecode_stream; - bytecode_stream:; - { - string_mapped = 1; - U64 bytecode_size = 0; - U64 off_first = block->location_data_off + sizeof(RDI_LocationKind); - U64 off_opl = all_location_data_size; - for(U64 off = off_first, next_off = off_opl; - off < all_location_data_size; - off = next_off) - { - next_off = off_opl; - U8 op = all_location_data[off]; - if(op == 0) - { - break; - } - U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; - U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); - bytecode_size += (1 + p_size); - next_off = (off + 1 + p_size); - } - mapped_bytecode = str8(all_location_data + off_first, bytecode_size); - }break; - case RDI_LocationKind_AddrRegPlusU16: - if(block->location_data_off + sizeof(RDI_LocationRegPlusU16) <= all_location_data_size) - { - string_mapped = 1; - RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); - E_OpList oplist = {0}; - U64 byte_size = bit_size_from_arch(arch)/8; - U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = space; - }break; - case RDI_LocationKind_AddrAddrRegPlusU16: - { - string_mapped = 1; - RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); - E_OpList oplist = {0}; - U64 byte_size = bit_size_from_arch(arch)/8; - U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_MemRead, e_value_u64(bit_size_from_arch(arch)/8)); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = space; - }break; - case RDI_LocationKind_ValReg: - if(block->location_data_off + sizeof(RDI_LocationReg) <= all_location_data_size) - { - string_mapped = 1; - RDI_LocationReg loc = *(RDI_LocationReg *)(all_location_data + block->location_data_off); - - REGS_RegCode regs_reg_code = regs_reg_code_from_arch_rdi_code(arch, loc.reg_code); - REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(arch)[regs_reg_code]; - E_OpList oplist = {0}; - U64 byte_size = (U64)reg_rng.byte_size; - U64 byte_pos = 0; - U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, byte_pos); - e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Value; - mapped_bytecode_space = space; - }break; - } - } - } - - //- rjf: try globals - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("global"), 0))) - { - for(U64 module_idx = 0; module_idx < e_ir_state->ctx->modules_count; module_idx += 1) - { - E_Module *module = &e_ir_state->ctx->modules[module_idx]; - RDI_Parsed *rdi = module->rdi; - RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables); - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); - for(String8Node *n = namespaceified_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[matches_count-1]; - RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, match_idx); - U32 type_idx = global_var->type_idx; - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); - E_OpList oplist = {0}; - e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff)); - string_mapped = 1; - mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = module->space; - break; - } - } - } - - //- rjf: try thread-locals - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("thread_local"), 0))) - { - for(U64 module_idx = 0; module_idx < e_ir_state->ctx->modules_count; module_idx += 1) - { - E_Module *module = &e_ir_state->ctx->modules[module_idx]; - RDI_Parsed *rdi = module->rdi; - RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_ThreadVariables); - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); - for(String8Node *n = namespaceified_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[matches_count-1]; - RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(rdi, ThreadVariables, match_idx); - U32 type_idx = thread_var->type_idx; - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); - E_OpList oplist = {0}; - e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off)); - string_mapped = 1; - mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = module->space; - break; - } - } - } - - //- rjf: try procedures - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("procedure"), 0))) - { - for(U64 module_idx = 0; module_idx < e_ir_state->ctx->modules_count; module_idx += 1) - { - E_Module *module = &e_ir_state->ctx->modules[module_idx]; - RDI_Parsed *rdi = module->rdi; - RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); - RDI_ParsedNameMap parsed_name_map = {0}; - rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); - RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); - U32 matches_count = 0; - U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); - for(String8Node *n = namespaceified_strings.first; - n != 0 && matches_count == 0; - n = n->next) - { - node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); - matches_count = 0; - matches = rdi_matches_from_map_node(rdi, node, &matches_count); - } - if(matches_count != 0) - { - U32 match_idx = matches[matches_count-1]; - RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, match_idx); - RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); - U64 voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); - U32 type_idx = procedure->type_idx; - RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); - E_OpList oplist = {0}; - e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff)); - string_mapped = 1; - mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Value; - mapped_bytecode_space = module->space; - break; - } - } - } - - //- rjf: try types - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("type"), 0))) - { - mapped_type_key = e_leaf_type_from_name(string); - if(!e_type_key_match(e_type_key_zero(), mapped_type_key)) - { - string_mapped = 1; - } - } - - //- rjf: try registers - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) - { - U64 reg_num = e_num_from_string(e_ir_state->ctx->regs_map, string); - if(reg_num != 0) - { - string_mapped = 1; - REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(e_parse_state->ctx->primary_module->arch)[reg_num]; - E_OpList oplist = {0}; - e_oplist_push_uconst(arena, &oplist, reg_rng.byte_off); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = e_ir_state->ctx->thread_reg_space; - mapped_type_key = e_type_key_reg(e_parse_state->ctx->primary_module->arch, reg_num); - } - } - - //- rjf: try register aliases - if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) - { - U64 alias_num = e_num_from_string(e_ir_state->ctx->reg_alias_map, string); - if(alias_num != 0) - { - string_mapped = 1; - REGS_Slice alias_slice = regs_alias_code_slice_table_from_arch(e_ir_state->ctx->primary_module->arch)[alias_num]; - REGS_Rng alias_reg_rng = regs_reg_code_rng_table_from_arch(e_ir_state->ctx->primary_module->arch)[alias_slice.code]; - E_OpList oplist = {0}; - e_oplist_push_uconst(arena, &oplist, alias_reg_rng.byte_off + alias_slice.byte_off); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Offset; - mapped_bytecode_space = e_ir_state->ctx->thread_reg_space; - mapped_type_key = e_type_key_reg_alias(e_parse_state->ctx->primary_module->arch, alias_num); - } - } - - //- rjf: try basic constants - if(!string_mapped && str8_match(string, str8_lit("true"), 0)) - { - string_mapped = 1; - E_OpList oplist = {0}; - e_oplist_push_uconst(arena, &oplist, 1); - mapped_type_key = e_type_key_basic(E_TypeKind_Bool); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Value; - } - if(!string_mapped && str8_match(string, str8_lit("false"), 0)) - { - string_mapped = 1; - E_OpList oplist = {0}; - e_oplist_push_uconst(arena, &oplist, 0); - mapped_type_key = e_type_key_basic(E_TypeKind_Bool); - mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); - mapped_bytecode_mode = E_Mode_Value; - } - - //- rjf: generate IR trees for bytecode - B32 generated = 0; - if(!generated && mapped_bytecode.size != 0) - { - generated = 1; - E_IRNode *root = e_irtree_bytecode_no_copy(arena, mapped_bytecode); - root->space = mapped_bytecode_space; - result.root = root; - result.type_key = mapped_type_key; - result.mode = mapped_bytecode_mode; - } - - //- rjf: generate nil-IR trees w/ type for types - if(!generated && !e_type_key_match(e_type_key_zero(), mapped_type_key)) - { - generated = 1; - result.type_key = mapped_type_key; - result.mode = E_Mode_Null; - } - - //- rjf: generate IR trees for macros - if(!generated) - { - E_Expr *macro_expr = e_string2expr_lookup(e_ir_state->ctx->macro_map, string); - if(macro_expr != &e_expr_nil) - { - generated = 1; - e_string2expr_map_inc_poison(e_ir_state->ctx->macro_map, string); - result = e_irtree_and_type_from_expr(arena, macro_expr); - e_string2expr_map_dec_poison(e_ir_state->ctx->macro_map, string); - } - } - - //- rjf: extend generation with member access, if original string was an - // implicit member access - if(generated && string_is_implicit_member_name) - { - // TODO(rjf): @cfg -#if 0 - E_LookupRule *lookup_rule = &e_lookup_rule__default; - E_LookupInfo lookup_info = lookup_rule->info(arena, &result, &e_expr_nil, str8_zero()); - E_LookupAccess lookup_access = lookup_rule->access(arena, E_ExprKind_MemberAccess, lhs, rhs, &e_expr_nil, lookup_info.user_data); - result = lookup_access.irtree_and_type; -#endif - } - - //- rjf: error on failure-to-generate - if(!generated) - { - e_msgf(arena, &result.msgs, E_MsgKind_ResolutionFailure, expr->location, "`%S` could not be found.", string); - } - - scratch_end(scratch); - }break; - - //- rjf: leaf offsets - case E_ExprKind_LeafOffset: - { - E_IRNode *new_tree = e_push_irnode(arena, RDI_EvalOp_ConstU64); - new_tree->value = expr->value; - new_tree->space = expr->space; - result.root = new_tree; - result.type_key = expr->type_key; - result.mode = E_Mode_Offset; - }break; - - //- rjf: leaf values - case E_ExprKind_LeafValue: - { - E_IRNode *new_tree = e_push_irnode(arena, RDI_EvalOp_ConstU128); - new_tree->value = expr->value; - new_tree->space = expr->space; - result.root = new_tree; - result.type_key = expr->type_key; - result.mode = E_Mode_Value; - }break; - - //- rjf: leaf file paths - case E_ExprKind_LeafFilePath: - { - Temp scratch = scratch_begin(&arena, 1); - String8 file_path = expr->string; - FileProperties props = os_properties_from_file_path(file_path); - if(!str8_match(expr->qualifier, str8_lit("folder"), 0) && !(props.flags & FilePropertyFlag_IsFolder) && file_path.size != 0) - { - E_Space space = e_space_make(E_SpaceKind_FileSystem); - result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(file_path))); - result.type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("file")); - result.mode = E_Mode_Value; - } - else - { - String8 folder_path = str8_chop_last_slash(file_path); - props = os_properties_from_file_path(folder_path); - if(props.flags & FilePropertyFlag_IsFolder || folder_path.size == 0 || str8_match(folder_path, str8_lit("/"), StringMatchFlag_SlashInsensitive)) - { - E_Space space = e_space_make(E_SpaceKind_FileSystem); - result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(folder_path))); - result.type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("folder")); - result.mode = E_Mode_Value; - } - } - scratch_end(scratch); - }break; - - //- rjf: types - case E_ExprKind_TypeIdent: - { - result.root = e_irtree_const_u(arena, 0); - result.root->space = expr->space; - result.type_key = expr->type_key; - result.mode = E_Mode_Null; - }break; - - //- rjf: (unexpected) type expressions - case E_ExprKind_Ptr: - case E_ExprKind_Array: - case E_ExprKind_Func: - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Type expression not expected."); - }break; - - //- rjf: definitions - case E_ExprKind_Define: - { - E_Expr *lhs = expr->first; - E_Expr *rhs = lhs->next; - result = e_irtree_and_type_from_expr(arena, rhs); - if(lhs->kind != E_ExprKind_LeafIdentifier) - { - e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Left side of assignment must be an unused identifier."); - } - }break; - } - return result; -} - internal E_IRTreeAndType -e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr) +e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); E_IRTreeAndType result = {&e_irnode_nil}; - if(expr->kind == E_ExprKind_Ref) - { - expr = expr->ref; - } + ////////////////////////////// //- rjf: apply all ir-generation steps + // typedef struct Task Task; struct Task { Task *next; E_Expr *expr; + E_Expr *parent_expr; + E_IRTreeAndType parent_irtree_and_type; }; - Task start_task = {0, expr}; + Task start_task = {0, root_expr, &e_expr_nil, {&e_irnode_nil}}; Task *first_task = &start_task; Task *last_task = first_task; for(Task *t = first_task; t != 0; t = t->next) { - // rjf: poison the tag we are about to use, so we don't recursively use it - e_expr_poison(t->expr); + E_Expr *expr = t->expr; - // rjf: do this rule's generation - result = e_irgen_rule__default.irgen(arena, t->expr); + //- rjf: poison the expression we are about to use, so we don't recursively use it + e_expr_poison(expr); - // rjf: find any auto hooks according to this generation's type + //- rjf: do expr -> irtree generation for this expression + if(expr->kind == E_ExprKind_Ref) + { + expr = expr->ref; + } + E_ExprKind kind = expr->kind; + switch(kind) + { + default:{}break; + + //- rjf: accesses + case E_ExprKind_MemberAccess: + case E_ExprKind_ArrayIndex: + { + // rjf: unpack left-hand-size + E_Expr *lhs = expr->first; + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); + + // 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); + }break; + + //- rjf: dereference + case E_ExprKind_Deref: + { + // rjf: unpack operand + E_Expr *r_expr = expr->first; + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + E_TypeKey r_type = e_type_unwrap(r_tree.type_key); + E_TypeKind r_type_kind = e_type_kind_from_key(r_type); + E_TypeKey r_type_direct = e_type_direct_from_key(r_type); + U64 r_type_direct_size = e_type_byte_size_from_key(r_type_direct); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + + // rjf: bad conditions? -> error if applicable, exit + if(r_tree.root->op == 0) + { + break; + } + else if(r_type_direct_size == 0 && + (r_type_kind == E_TypeKind_Ptr || + r_type_kind == E_TypeKind_LRef || + r_type_kind == E_TypeKind_RRef)) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->location, "Cannot dereference pointers of zero-sized types."); + break; + } + else if(r_type_direct_size == 0 && r_type_kind == E_TypeKind_Array) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->location, "Cannot dereference arrays of zero-sized types."); + break; + } + else if(r_type_kind != E_TypeKind_Array && + r_type_kind != E_TypeKind_Ptr && + r_type_kind != E_TypeKind_LRef && + r_type_kind != E_TypeKind_RRef) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, r_expr->location, "Cannot dereference this type."); + break; + } + + // rjf: generate + { + E_IRNode *new_tree = r_tree.root; + if(r_tree.mode != E_Mode_Value && + (r_type_kind == E_TypeKind_Ptr || + r_type_kind == E_TypeKind_LRef || + r_type_kind == E_TypeKind_RRef)) + { + new_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); + } + result.root = new_tree; + result.type_key = r_type_direct; + result.mode = E_Mode_Offset; + } + }break; + + //- rjf: address-of + case E_ExprKind_Address: + { + // rjf: unpack operand + E_Expr *r_expr = expr->first; + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + E_TypeKey r_type = r_tree.type_key; + E_TypeKey r_type_unwrapped = e_type_unwrap(r_type); + E_TypeKind r_type_unwrapped_kind = e_type_kind_from_key(r_type_unwrapped); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + + // rjf: bad conditions? -> error if applicable, exit + if(r_tree.root->op == 0) + { + break; + } + else if(e_type_key_match(e_type_key_zero(), r_type_unwrapped)) + { + break; + } + + // rjf: generate + result.root = r_tree.root; + result.type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, r_type_unwrapped, 1, 0); + result.mode = E_Mode_Value; + }break; + + //- rjf: cast + case E_ExprKind_Cast: + { + // rjf: unpack operands + E_Expr *cast_type_expr = expr->first; + E_Expr *casted_expr = cast_type_expr->next; + E_TypeKey cast_type = e_type_from_expr(cast_type_expr); + E_TypeKind cast_type_kind = e_type_kind_from_key(cast_type); + U64 cast_type_byte_size = e_type_byte_size_from_key(cast_type); + E_IRTreeAndType casted_tree = e_irtree_and_type_from_expr(arena, casted_expr); + e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs); + E_TypeKey casted_type = e_type_unwrap(casted_tree.type_key); + E_TypeKind casted_type_kind = e_type_kind_from_key(casted_type); + U64 casted_type_byte_size = e_type_byte_size_from_key(casted_type); + U8 in_group = e_type_group_from_kind(casted_type_kind); + U8 out_group = e_type_group_from_kind(cast_type_kind); + RDI_EvalConversionKind conversion_rule = rdi_eval_conversion_kind_from_typegroups(in_group, out_group); + + // rjf: bad conditions? -> error if applicable, exit + if(casted_tree.root->op == 0) + { + break; + } + else if(cast_type_kind == E_TypeKind_Null) + { + break; + } + else if(conversion_rule != RDI_EvalConversionKind_Noop && + conversion_rule != RDI_EvalConversionKind_Legal) + { + String8 text = str8_lit("Unknown cast conversion rule."); + if(conversion_rule < RDI_EvalConversionKind_COUNT) + { + text.str = rdi_explanation_string_from_eval_conversion_kind(conversion_rule, &text.size); + } + e_msg(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, text); + break; + } + + // rjf: generate + { + E_IRNode *in_tree = e_irtree_resolve_to_value(arena, casted_tree.mode, casted_tree.root, casted_type); + E_IRNode *new_tree = in_tree; + if(conversion_rule == RDI_EvalConversionKind_Legal) + { + new_tree = e_irtree_convert_lo(arena, in_tree, out_group, in_group); + } + if(cast_type_byte_size < casted_type_byte_size && e_type_kind_is_integer(cast_type_kind)) + { + new_tree = e_irtree_trunc(arena, in_tree, cast_type); + } + result.root = new_tree; + result.type_key = cast_type; + result.mode = E_Mode_Value; + } + }break; + + //- rjf: sizeof + case E_ExprKind_Sizeof: + { + // rjf: unpack operand + E_Expr *r_expr = expr->first; + E_TypeKey r_type = zero_struct; + E_Space space = r_expr->space; + switch(r_expr->kind) + { + case E_ExprKind_TypeIdent: + case E_ExprKind_Ptr: + case E_ExprKind_Array: + case E_ExprKind_Func: + { + r_type = e_type_from_expr(r_expr); + }break; + default: + { + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + r_type = r_tree.type_key; + }break; + } + + // rjf: bad conditions? -> error if applicable, exit + if(e_type_key_match(r_type, e_type_key_zero())) + { + break; + } + else if(e_type_kind_from_key(r_type) == E_TypeKind_Null) + { + break; + } + + // rjf: generate + { + U64 r_type_byte_size = e_type_byte_size_from_key(r_type); + result.root = e_irtree_const_u(arena, r_type_byte_size); + result.type_key = e_type_key_basic(E_TypeKind_U64); + result.mode = E_Mode_Value; + } + }break; + + //- rjf: typeof + case E_ExprKind_Typeof: + { + // rjf: evaluate operand tree + E_Expr *r_expr = expr->first; + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + + // rjf: fill output + result.root = e_irtree_const_u(arena, 0); + result.type_key = r_tree.type_key; + result.mode = E_Mode_Null; + }break; + + //- rjf: byteswap + case E_ExprKind_ByteSwap: + { + // rjf: unpack operand + E_Expr *r_expr = expr->first; + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + E_TypeKey r_type = e_type_unwrap(r_tree.type_key); + E_TypeKind r_type_kind = e_type_kind_from_key(r_type); + U64 r_type_size = e_type_byte_size_from_key(r_type); + + // rjf: bad conditions? -> error if applicable, exit + if(!e_type_kind_is_integer(r_type_kind) || (r_type_size != 8 && r_type_size != 4 && r_type_size != 2)) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Byteswapping this type is not supported."); + break; + } + + // rjf: generate + { + E_IRNode *node = e_push_irnode(arena, RDI_EvalOp_ByteSwap); + E_IRNode *rhs = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); + e_irnode_push_child(node, rhs); + node->value.u64 = r_type_size; + result.root = node; + result.mode = E_Mode_Value; + result.type_key = r_type; + } + }break; + + //- rjf: unary operations + case E_ExprKind_Pos: + { + result = e_irtree_and_type_from_expr(arena, expr->first); + }break; + case E_ExprKind_Neg: + case E_ExprKind_BitNot: + { + // rjf: unpack operand + E_Expr *r_expr = expr->first; + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + E_TypeKey r_type = e_type_unwrap(r_tree.type_key); + E_TypeKind r_type_kind = e_type_kind_from_key(r_type); + RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); + E_TypeKey r_type_promoted = e_type_promote(r_type); + RDI_EvalOp op = e_opcode_from_expr_kind(kind); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + + // rjf: bad conditions? -> error if applicable, exit + if(r_tree.root->op == 0) + { + break; + } + else if(!rdi_eval_op_typegroup_are_compatible(op, r_type_group)) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Cannot use this operator on this type."); + break; + } + + // rjf: generate + { + E_IRNode *in_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); + in_tree = e_irtree_convert_hi(arena, in_tree, r_type_promoted, r_type); + E_IRNode *new_tree = e_irtree_unary_op(arena, op, r_type_group, in_tree); + result.root = new_tree; + result.type_key = r_type_promoted; + result.mode = E_Mode_Value; + } + }break; + case E_ExprKind_LogNot: + { + // rjf: unpack operand + E_Expr *r_expr = expr->first; + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + E_TypeKey r_type = e_type_unwrap(r_tree.type_key); + E_TypeKind r_type_kind = e_type_kind_from_key(r_type); + RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); + E_TypeKey r_type_promoted = e_type_key_basic(E_TypeKind_Bool); + RDI_EvalOp op = e_opcode_from_expr_kind(kind); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + + // rjf: bad conditions? -> error if applicable, exit + if(r_tree.root->op == 0) + { + break; + } + else if(!rdi_eval_op_typegroup_are_compatible(op, r_type_group)) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Cannot use this operator on this type."); + break; + } + + // rjf: generate + { + E_IRNode *in_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); + in_tree = e_irtree_convert_hi(arena, in_tree, r_type_promoted, r_type); + E_IRNode *new_tree = e_irtree_unary_op(arena, op, r_type_group, in_tree); + result.root = new_tree; + result.type_key = r_type_promoted; + result.mode = E_Mode_Value; + } + }break; + + //- rjf: binary operations + case E_ExprKind_Mul: + case E_ExprKind_Div: + case E_ExprKind_Mod: + case E_ExprKind_Add: + case E_ExprKind_Sub: + case E_ExprKind_LShift: + case E_ExprKind_RShift: + case E_ExprKind_Less: + case E_ExprKind_LsEq: + case E_ExprKind_Grtr: + case E_ExprKind_GrEq: + case E_ExprKind_EqEq: + case E_ExprKind_NtEq: + case E_ExprKind_BitAnd: + case E_ExprKind_BitXor: + case E_ExprKind_BitOr: + case E_ExprKind_LogAnd: + case E_ExprKind_LogOr: + { + // rjf: unpack operands + RDI_EvalOp op = e_opcode_from_expr_kind(kind); + B32 is_comparison = e_expr_kind_is_comparison(kind); + E_Expr *l_expr = expr->first; + E_Expr *r_expr = l_expr->next; + E_IRTreeAndType l_tree = e_irtree_and_type_from_expr(arena, l_expr); + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + E_TypeKey l_type = e_type_unwrap_enum(e_type_unwrap(l_tree.type_key)); + E_TypeKey r_type = e_type_unwrap_enum(e_type_unwrap(r_tree.type_key)); + E_TypeKind l_type_kind = e_type_kind_from_key(l_type); + E_TypeKind r_type_kind = e_type_kind_from_key(r_type); + if(l_type.kind == E_TypeKeyKind_Reg) + { + l_type_kind = E_TypeKind_U64; + l_type = e_type_key_basic(l_type_kind); + } + if(r_type.kind == E_TypeKeyKind_Reg) + { + r_type_kind = E_TypeKind_U64; + r_type = e_type_key_basic(r_type_kind); + } + B32 l_is_pointer = (l_type_kind == E_TypeKind_Ptr); + B32 l_is_decay = (l_type_kind == E_TypeKind_Array && l_tree.mode == E_Mode_Offset); + B32 l_is_pointer_like = (l_is_pointer || l_is_decay); + B32 r_is_pointer = (r_type_kind == E_TypeKind_Ptr); + B32 r_is_decay = (r_type_kind == E_TypeKind_Array && r_tree.mode == E_Mode_Offset); + B32 r_is_pointer_like = (r_is_pointer || r_is_decay); + RDI_EvalTypeGroup l_type_group = e_type_group_from_kind(l_type_kind); + RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind); + + // rjf: bad conditions? -> error if applicable, exit + if(l_tree.root->op == 0 || r_tree.root->op == 0) + { + break; + } + + // rjf: determine arithmetic path +#define E_ArithPath_Normal 0 +#define E_ArithPath_PtrAdd 1 +#define E_ArithPath_PtrSub 2 +#define E_ArithPath_PtrArrayCompare 3 + B32 ptr_arithmetic_mul_rptr = 0; + U32 arith_path = E_ArithPath_Normal; + if(kind == E_ExprKind_Add) + { + if(l_is_pointer_like && e_type_kind_is_integer(r_type_kind)) + { + arith_path = E_ArithPath_PtrAdd; + } + if(l_is_pointer_like && e_type_kind_is_integer(l_type_kind)) + { + arith_path = E_ArithPath_PtrAdd; + ptr_arithmetic_mul_rptr = 1; + } + } + else if(kind == E_ExprKind_Sub) + { + if(l_is_pointer_like && e_type_kind_is_integer(r_type_kind)) + { + arith_path = E_ArithPath_PtrAdd; + } + if(l_is_pointer_like && r_is_pointer_like) + { + E_TypeKey l_type_direct = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(l_type))); + E_TypeKey r_type_direct = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(r_type))); + U64 l_type_direct_byte_size = e_type_byte_size_from_key(l_type_direct); + U64 r_type_direct_byte_size = e_type_byte_size_from_key(r_type_direct); + if(l_type_direct_byte_size == r_type_direct_byte_size) + { + arith_path = E_ArithPath_PtrSub; + } + } + } + else if(kind == E_ExprKind_EqEq) + { + if(l_type_kind == E_TypeKind_Array && (r_type_kind == E_TypeKind_Ptr || r_is_decay)) + { + arith_path = E_ArithPath_PtrArrayCompare; + } + if(r_type_kind == E_TypeKind_Array && (l_type_kind == E_TypeKind_Ptr || l_is_decay)) + { + arith_path = E_ArithPath_PtrArrayCompare; + } + } + + // rjf: generate according to arithmetic path + switch(arith_path) + { + //- rjf: normal arithmetic + case E_ArithPath_Normal: + { + // rjf: bad conditions? -> error if applicable, exit + if(!rdi_eval_op_typegroup_are_compatible(op, l_type_group) || + !rdi_eval_op_typegroup_are_compatible(op, r_type_group)) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Cannot use this operator on this type."); + break; + } + + // rjf: generate + { + E_TypeKey final_type_key = is_comparison ? e_type_key_basic(E_TypeKind_Bool) : l_type; + E_IRNode *l_value_tree = e_irtree_resolve_to_value(arena, l_tree.mode, l_tree.root, l_type); + E_IRNode *r_value_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); + l_value_tree = e_irtree_convert_hi(arena, l_value_tree, l_type, l_type); + r_value_tree = e_irtree_convert_hi(arena, r_value_tree, l_type, r_type); + E_IRNode *new_tree = e_irtree_binary_op(arena, op, l_type_group, l_value_tree, r_value_tree); + result.root = new_tree; + result.type_key = final_type_key; + result.mode = E_Mode_Value; + } + }break; + + //- rjf: pointer addition + case E_ArithPath_PtrAdd: + { + // rjf: map l/r to ptr/int + E_IRTreeAndType *ptr_tree = &l_tree; + E_IRTreeAndType *int_tree = &r_tree; + B32 ptr_is_decay = l_is_decay; + if(ptr_arithmetic_mul_rptr) + { + ptr_tree = &r_tree; + int_tree = &l_tree; + ptr_is_decay = r_is_decay; + } + + // rjf: unpack type + E_TypeKey direct_type = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(ptr_tree->type_key))); + U64 direct_type_size = e_type_byte_size_from_key(direct_type); + + // rjf: generate + { + E_IRNode *ptr_root = ptr_tree->root; + if(!ptr_is_decay) + { + ptr_root = e_irtree_resolve_to_value(arena, ptr_tree->mode, ptr_root, ptr_tree->type_key); + } + E_IRNode *int_root = int_tree->root; + int_root = e_irtree_resolve_to_value(arena, int_tree->mode, int_root, int_tree->type_key); + if(direct_type_size > 1) + { + E_IRNode *const_root = e_irtree_const_u(arena, direct_type_size); + int_root = e_irtree_binary_op_u(arena, RDI_EvalOp_Mul, int_root, const_root); + } + E_TypeKey ptr_type = ptr_tree->type_key; + if(ptr_is_decay) + { + ptr_type = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, direct_type, 1, 0); + } + E_IRNode *new_root = e_irtree_binary_op_u(arena, op, ptr_root, int_root); + result.root = new_root; + result.type_key = ptr_type; + result.mode = E_Mode_Value; + } + }break; + + //- rjf: pointer subtraction + case E_ArithPath_PtrSub: + { + // rjf: unpack type + E_TypeKey direct_type = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(l_type))); + U64 direct_type_size = e_type_byte_size_from_key(direct_type); + + // rjf: generate + E_IRNode *l_root = l_tree.root; + E_IRNode *r_root = r_tree.root; + if(!l_is_decay) + { + l_root = e_irtree_resolve_to_value(arena, l_tree.mode, l_root, l_type); + } + if(!r_is_decay) + { + r_root = e_irtree_resolve_to_value(arena, r_tree.mode, r_root, r_type); + } + E_IRNode *op_tree = e_irtree_binary_op_u(arena, op, l_root, r_root); + E_IRNode *new_tree = op_tree; + if(direct_type_size > 1) + { + E_IRNode *const_tree = e_irtree_const_u(arena, direct_type_size); + new_tree = e_irtree_binary_op_u(arena, RDI_EvalOp_Div, new_tree, const_tree); + } + result.root = new_tree; + result.type_key = e_type_key_basic(E_TypeKind_U64); + result.mode = E_Mode_Value; + }break; + + //- rjf: pointer array comparison + case E_ArithPath_PtrArrayCompare: + { + // rjf: map l/r to pointer/array + B32 ptr_is_decay = l_is_decay; + E_IRTreeAndType *ptr_tree = &l_tree; + E_IRTreeAndType *arr_tree = &r_tree; + if(l_type_kind == E_TypeKind_Array && l_tree.mode == E_Mode_Value) + { + ptr_is_decay = r_is_decay; + ptr_tree = &r_tree; + arr_tree = &l_tree; + } + + // rjf: resolve pointer to value, sized same as array + E_IRNode *ptr_root = ptr_tree->root; + E_IRNode *arr_root = arr_tree->root; + if(!ptr_is_decay) + { + ptr_root = e_irtree_resolve_to_value(arena, ptr_tree->mode, ptr_tree->root, ptr_tree->type_key); + } + + // rjf: read from pointer into value, to compare with array + E_IRNode *mem_root = e_irtree_mem_read_type(arena, ptr_root, arr_tree->type_key); + + // rjf: generate + result.root = e_irtree_binary_op(arena, op, RDI_EvalTypeGroup_Other, mem_root, arr_root); + result.type_key = e_type_key_basic(E_TypeKind_Bool); + result.mode = E_Mode_Value; + }break; + } + }break; + + //- rjf: ternary operators + case E_ExprKind_Ternary: + { + // rjf: unpack operands + E_Expr *c_expr = expr->first; + E_Expr *l_expr = c_expr->next; + E_Expr *r_expr = l_expr->next; + E_IRTreeAndType c_tree = e_irtree_and_type_from_expr(arena, c_expr); + E_IRTreeAndType l_tree = e_irtree_and_type_from_expr(arena, l_expr); + E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr); + e_msg_list_concat_in_place(&result.msgs, &c_tree.msgs); + e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); + E_TypeKey c_type = e_type_unwrap(c_tree.type_key); + E_TypeKey l_type = e_type_unwrap(l_tree.type_key); + E_TypeKey r_type = e_type_unwrap(r_tree.type_key); + E_TypeKind c_type_kind = e_type_kind_from_key(c_type); + E_TypeKind l_type_kind = e_type_kind_from_key(l_type); + E_TypeKind r_type_kind = e_type_kind_from_key(r_type); + E_TypeKey result_type = l_type; + + // rjf: bad conditions? -> error if applicable, exit + if(c_tree.root->op == 0 || l_tree.root->op == 0 || r_tree.root->op == 0) + { + break; + } + else if(!e_type_kind_is_integer(c_type_kind) && c_type_kind != E_TypeKind_Bool) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Conditional term must be an integer or boolean type."); + } + else if(!e_type_match(l_type, r_type)) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Left and right terms must have matching types."); + } + + // rjf: generate + { + E_IRNode *c_value_tree = e_irtree_resolve_to_value(arena, c_tree.mode, c_tree.root, c_type); + E_IRNode *l_value_tree = e_irtree_resolve_to_value(arena, l_tree.mode, l_tree.root, l_type); + E_IRNode *r_value_tree = e_irtree_resolve_to_value(arena, r_tree.mode, r_tree.root, r_type); + l_value_tree = e_irtree_convert_hi(arena, l_value_tree, result_type, l_type); + r_value_tree = e_irtree_convert_hi(arena, r_value_tree, result_type, r_type); + E_IRNode *new_tree = e_irtree_conditional(arena, c_value_tree, l_value_tree, r_value_tree); + result.root = new_tree; + result.type_key = result_type; + result.mode = E_Mode_Value; + } + }break; + + //- rjf: call + case E_ExprKind_Call: + { + E_Expr *lhs = expr->first; + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); + E_TypeKey lhs_type_key = lhs_irtree.type_key; + E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); + + // 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) + { + Temp scratch = scratch_begin(&arena, 1); + + // rjf: generate result via first argument to lens + result = e_irtree_and_type_from_expr(arena, lhs->next); + + // rjf: count extra arguments + U64 arg_count = 0; + for(E_Expr *arg = lhs->next->next; arg != &e_expr_nil; arg = arg->next) + { + arg_count += 1; + } + + // rjf: flatten extra arguments + E_Expr **args = push_array(scratch.arena, E_Expr *, arg_count); + { + U64 idx = 0; + for(E_Expr *arg = lhs->next->next; arg != &e_expr_nil; arg = arg->next, idx += 1) + { + args[idx] = arg; + } + } + + // rjf: patch resultant type with a lens w/ args, pointing to the original type + result.type_key = e_type_key_cons(.kind = E_TypeKind_Lens, .count = arg_count, .args = args, .direct_key = result.type_key, .name = lhs_type->name); + + scratch_end(scratch); + } + else + { + e_msgf(arena, &result.msgs, E_MsgKind_InterpretationError, expr->location, "Calling this type is not supported."); + } + }break; + + //- rjf: leaf bytecode + case E_ExprKind_LeafBytecode: + { + E_IRNode *new_tree = e_irtree_bytecode_no_copy(arena, expr->bytecode); + new_tree->space = expr->space; + E_TypeKey final_type_key = expr->type_key; + result.root = new_tree; + result.type_key = final_type_key; + result.mode = expr->mode; + }break; + + //- rjf: leaf string literal + case E_ExprKind_LeafStringLiteral: + { + String8 string = expr->string; + E_TypeKey type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_UChar8), string.size, 0); + E_IRNode *new_tree = e_irtree_string_literal(arena, string); + result.root = new_tree; + result.type_key = type_key; + result.mode = E_Mode_Value; + }break; + + //- rjf: leaf U64s + case E_ExprKind_LeafU64: + { + U64 val = expr->value.u64; + E_IRNode *new_tree = e_irtree_const_u(arena, val); + E_TypeKey type_key = zero_struct; + if(0){} + else if(val <= max_S32){type_key = e_type_key_basic(E_TypeKind_S32);} + else if(val <= max_S64){type_key = e_type_key_basic(E_TypeKind_S64);} + else {type_key = e_type_key_basic(E_TypeKind_U64);} + result.root = new_tree; + result.type_key = type_key; + result.mode = E_Mode_Value; + }break; + + //- rjf: leaf F64s + case E_ExprKind_LeafF64: + { + U64 val = expr->value.u64; + E_IRNode *new_tree = e_irtree_const_u(arena, val); + result.root = new_tree; + result.type_key = e_type_key_basic(E_TypeKind_F64); + result.mode = E_Mode_Value; + }break; + + //- rjf: leaf F32s + case E_ExprKind_LeafF32: + { + U32 val = expr->value.u32; + E_IRNode *new_tree = e_irtree_const_u(arena, val); + result.root = new_tree; + result.type_key = e_type_key_basic(E_TypeKind_F32); + result.mode = E_Mode_Value; + }break; + + //- rjf: leaf identifiers + case E_ExprKind_LeafIdentifier: + { + Temp scratch = scratch_begin(&arena, 1); + String8 qualifier = expr->qualifier; + String8 string = expr->string; + String8 string__redirected = string; + B32 string_mapped = 0; + E_TypeKey mapped_type_key = zero_struct; + E_Module *mapped_location_block_module = &e_module_nil; + RDI_LocationBlock *mapped_location_block = 0; + + //- rjf: form namespaceified fallback versions of this lookup string + String8List namespaceified_strings = {0}; + { + E_Module *module = e_ir_state->ctx->primary_module; + RDI_Parsed *rdi = module->rdi; + RDI_Procedure *procedure = e_ir_state->thread_ip_procedure; + U64 name_size = 0; + U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size); + String8 containing_procedure_name = str8(name_ptr, name_size); + U64 last_past_scope_resolution_pos = 0; + for(;;) + { + U64 past_next_dbl_colon_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("::"), 0)+2; + U64 past_next_dot_pos = str8_find_needle(containing_procedure_name, last_past_scope_resolution_pos, str8_lit("."), 0)+1; + U64 past_next_scope_resolution_pos = Min(past_next_dbl_colon_pos, past_next_dot_pos); + if(past_next_scope_resolution_pos >= containing_procedure_name.size) + { + break; + } + String8 new_namespace_prefix_possibility = str8_prefix(containing_procedure_name, past_next_scope_resolution_pos); + String8 namespaceified_string = push_str8f(scratch.arena, "%S%S", new_namespace_prefix_possibility, string); + str8_list_push_front(scratch.arena, &namespaceified_strings, namespaceified_string); + last_past_scope_resolution_pos = past_next_scope_resolution_pos; + } + } + + //- rjf: try to map name as member - if found, string__redirected := "this", and turn + // on later implicit-member-lookup generation + B32 string_is_implicit_member_name = 0; + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("member"), 0))) + { + E_Module *module = e_ir_state->ctx->primary_module; + U32 module_idx = (U32)(module - e_ir_state->ctx->modules); + RDI_Parsed *rdi = module->rdi; + RDI_Procedure *procedure = e_ir_state->thread_ip_procedure; + RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure); + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx); + E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module_idx); + E_Member member = e_type_member_from_key_name__cached(container_type_key, string); + if(member.kind != E_MemberKind_Null) + { + string_is_implicit_member_name = 1; + string__redirected = str8_lit("this"); + } + } + + //- rjf: try locals + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("local"), 0))) + { + E_Module *module = e_ir_state->ctx->primary_module; + U32 module_idx = (U32)(module - e_ir_state->ctx->modules); + RDI_Parsed *rdi = module->rdi; + U64 local_num = e_num_from_string(e_ir_state->ctx->locals_map, string__redirected); + if(local_num != 0) + { + RDI_Local *local = rdi_element_from_name_idx(rdi, Locals, local_num-1); + + // rjf: extract local's type key + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, local->type_idx); + mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module_idx); + + // rjf: extract local's location block + U64 ip_voff = e_ir_state->ctx->thread_ip_voff; + for(U32 loc_block_idx = local->location_first; + loc_block_idx < local->location_opl; + loc_block_idx += 1) + { + RDI_LocationBlock *block = rdi_element_from_name_idx(rdi, LocationBlocks, loc_block_idx); + if(block->scope_off_first <= ip_voff && ip_voff < block->scope_off_opl) + { + mapped_location_block_module = module; + mapped_location_block = block; + } + } + } + } + + //- rjf: mapped to location block -> extract or produce bytecode for this mapping + E_Mode mapped_bytecode_mode = E_Mode_Offset; + E_Space mapped_bytecode_space = zero_struct; + String8 mapped_bytecode = {0}; + if(mapped_location_block != 0) + { + E_Module *module = mapped_location_block_module; + E_Space space = module->space; + Arch arch = module->arch; + RDI_Parsed *rdi = module->rdi; + RDI_LocationBlock *block = mapped_location_block; + U64 all_location_data_size = 0; + U8 *all_location_data = rdi_table_from_name(rdi, LocationData, &all_location_data_size); + if(block->location_data_off + sizeof(RDI_LocationKind) <= all_location_data_size) + { + RDI_LocationKind loc_kind = *((RDI_LocationKind *)(all_location_data + block->location_data_off)); + switch(loc_kind) + { + default:{}break; + case RDI_LocationKind_ValBytecodeStream: {mapped_bytecode_mode = E_Mode_Value;}goto bytecode_stream; + case RDI_LocationKind_AddrBytecodeStream:{mapped_bytecode_mode = E_Mode_Offset;}goto bytecode_stream; + bytecode_stream:; + { + string_mapped = 1; + U64 bytecode_size = 0; + U64 off_first = block->location_data_off + sizeof(RDI_LocationKind); + U64 off_opl = all_location_data_size; + for(U64 off = off_first, next_off = off_opl; + off < all_location_data_size; + off = next_off) + { + next_off = off_opl; + U8 op = all_location_data[off]; + if(op == 0) + { + break; + } + U16 ctrlbits = rdi_eval_op_ctrlbits_table[op]; + U32 p_size = RDI_DECODEN_FROM_CTRLBITS(ctrlbits); + bytecode_size += (1 + p_size); + next_off = (off + 1 + p_size); + } + mapped_bytecode = str8(all_location_data + off_first, bytecode_size); + }break; + case RDI_LocationKind_AddrRegPlusU16: + if(block->location_data_off + sizeof(RDI_LocationRegPlusU16) <= all_location_data_size) + { + string_mapped = 1; + RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); + E_OpList oplist = {0}; + U64 byte_size = bit_size_from_arch(arch)/8; + U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = space; + }break; + case RDI_LocationKind_AddrAddrRegPlusU16: + { + string_mapped = 1; + RDI_LocationRegPlusU16 loc = *(RDI_LocationRegPlusU16 *)(all_location_data + block->location_data_off); + E_OpList oplist = {0}; + U64 byte_size = bit_size_from_arch(arch)/8; + U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, 0); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU16, e_value_u64(loc.offset)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_Add, e_value_u64(0)); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_MemRead, e_value_u64(bit_size_from_arch(arch)/8)); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = space; + }break; + case RDI_LocationKind_ValReg: + if(block->location_data_off + sizeof(RDI_LocationReg) <= all_location_data_size) + { + string_mapped = 1; + RDI_LocationReg loc = *(RDI_LocationReg *)(all_location_data + block->location_data_off); + + REGS_RegCode regs_reg_code = regs_reg_code_from_arch_rdi_code(arch, loc.reg_code); + REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(arch)[regs_reg_code]; + E_OpList oplist = {0}; + U64 byte_size = (U64)reg_rng.byte_size; + U64 byte_pos = 0; + U64 regread_param = RDI_EncodeRegReadParam(loc.reg_code, byte_size, byte_pos); + e_oplist_push_op(arena, &oplist, RDI_EvalOp_RegRead, e_value_u64(regread_param)); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Value; + mapped_bytecode_space = space; + }break; + } + } + } + + //- rjf: try globals + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("global"), 0))) + { + for(U64 module_idx = 0; module_idx < e_ir_state->ctx->modules_count; module_idx += 1) + { + E_Module *module = &e_ir_state->ctx->modules[module_idx]; + RDI_Parsed *rdi = module->rdi; + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_GlobalVariables); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); + for(String8Node *n = namespaceified_strings.first; + n != 0 && matches_count == 0; + n = n->next) + { + node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[matches_count-1]; + RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, match_idx); + U32 type_idx = global_var->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff)); + string_mapped = 1; + mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = module->space; + break; + } + } + } + + //- rjf: try thread-locals + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("thread_local"), 0))) + { + for(U64 module_idx = 0; module_idx < e_ir_state->ctx->modules_count; module_idx += 1) + { + E_Module *module = &e_ir_state->ctx->modules[module_idx]; + RDI_Parsed *rdi = module->rdi; + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_ThreadVariables); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); + for(String8Node *n = namespaceified_strings.first; + n != 0 && matches_count == 0; + n = n->next) + { + node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[matches_count-1]; + RDI_ThreadVariable *thread_var = rdi_element_from_name_idx(rdi, ThreadVariables, match_idx); + U32 type_idx = thread_var->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off)); + string_mapped = 1; + mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = module->space; + break; + } + } + } + + //- rjf: try procedures + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("procedure"), 0))) + { + for(U64 module_idx = 0; module_idx < e_ir_state->ctx->modules_count; module_idx += 1) + { + E_Module *module = &e_ir_state->ctx->modules[module_idx]; + RDI_Parsed *rdi = module->rdi; + RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Procedures); + RDI_ParsedNameMap parsed_name_map = {0}; + rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map); + RDI_NameMapNode *node = rdi_name_map_lookup(rdi, &parsed_name_map, string.str, string.size); + U32 matches_count = 0; + U32 *matches = rdi_matches_from_map_node(rdi, node, &matches_count); + for(String8Node *n = namespaceified_strings.first; + n != 0 && matches_count == 0; + n = n->next) + { + node = rdi_name_map_lookup(rdi, &parsed_name_map, n->string.str, n->string.size); + matches_count = 0; + matches = rdi_matches_from_map_node(rdi, node, &matches_count); + } + if(matches_count != 0) + { + U32 match_idx = matches[matches_count-1]; + RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, match_idx); + RDI_Scope *scope = rdi_element_from_name_idx(rdi, Scopes, procedure->root_scope_idx); + U64 voff = *rdi_element_from_name_idx(rdi, ScopeVOffData, scope->voff_range_first); + U32 type_idx = procedure->type_idx; + RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx); + E_OpList oplist = {0}; + e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff)); + string_mapped = 1; + mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)module_idx); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Value; + mapped_bytecode_space = module->space; + break; + } + } + } + + //- rjf: try types + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("type"), 0))) + { + mapped_type_key = e_leaf_type_from_name(string); + if(!e_type_key_match(e_type_key_zero(), mapped_type_key)) + { + string_mapped = 1; + } + } + + //- rjf: try registers + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) + { + U64 reg_num = e_num_from_string(e_ir_state->ctx->regs_map, string); + if(reg_num != 0) + { + string_mapped = 1; + REGS_Rng reg_rng = regs_reg_code_rng_table_from_arch(e_parse_state->ctx->primary_module->arch)[reg_num]; + E_OpList oplist = {0}; + e_oplist_push_uconst(arena, &oplist, reg_rng.byte_off); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = e_ir_state->ctx->thread_reg_space; + mapped_type_key = e_type_key_reg(e_parse_state->ctx->primary_module->arch, reg_num); + } + } + + //- rjf: try register aliases + if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("reg"), 0))) + { + U64 alias_num = e_num_from_string(e_ir_state->ctx->reg_alias_map, string); + if(alias_num != 0) + { + string_mapped = 1; + REGS_Slice alias_slice = regs_alias_code_slice_table_from_arch(e_ir_state->ctx->primary_module->arch)[alias_num]; + REGS_Rng alias_reg_rng = regs_reg_code_rng_table_from_arch(e_ir_state->ctx->primary_module->arch)[alias_slice.code]; + E_OpList oplist = {0}; + e_oplist_push_uconst(arena, &oplist, alias_reg_rng.byte_off + alias_slice.byte_off); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Offset; + mapped_bytecode_space = e_ir_state->ctx->thread_reg_space; + mapped_type_key = e_type_key_reg_alias(e_parse_state->ctx->primary_module->arch, alias_num); + } + } + + //- rjf: try basic constants + if(!string_mapped && str8_match(string, str8_lit("true"), 0)) + { + string_mapped = 1; + E_OpList oplist = {0}; + e_oplist_push_uconst(arena, &oplist, 1); + mapped_type_key = e_type_key_basic(E_TypeKind_Bool); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Value; + } + if(!string_mapped && str8_match(string, str8_lit("false"), 0)) + { + string_mapped = 1; + E_OpList oplist = {0}; + e_oplist_push_uconst(arena, &oplist, 0); + mapped_type_key = e_type_key_basic(E_TypeKind_Bool); + mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); + mapped_bytecode_mode = E_Mode_Value; + } + + //- rjf: generate IR trees for bytecode + B32 generated = 0; + if(!generated && mapped_bytecode.size != 0) + { + generated = 1; + E_IRNode *root = e_irtree_bytecode_no_copy(arena, mapped_bytecode); + root->space = mapped_bytecode_space; + result.root = root; + result.type_key = mapped_type_key; + result.mode = mapped_bytecode_mode; + } + + //- rjf: generate nil-IR trees w/ type for types + if(!generated && !e_type_key_match(e_type_key_zero(), mapped_type_key)) + { + generated = 1; + result.type_key = mapped_type_key; + result.mode = E_Mode_Null; + } + + //- rjf: generate IR trees for macros + if(!generated) + { + E_Expr *macro_expr = e_string2expr_lookup(e_ir_state->ctx->macro_map, string); + if(macro_expr != &e_expr_nil) + { + generated = 1; + e_string2expr_map_inc_poison(e_ir_state->ctx->macro_map, string); + result = e_irtree_and_type_from_expr(arena, macro_expr); + e_string2expr_map_dec_poison(e_ir_state->ctx->macro_map, string); + } + } + + //- rjf: extend generation with member access, if original string was an + // implicit member access + if(generated && string_is_implicit_member_name) + { + // TODO(rjf): @cfg +#if 0 + E_LookupRule *lookup_rule = &e_lookup_rule__default; + E_LookupInfo lookup_info = lookup_rule->info(arena, &result, &e_expr_nil, str8_zero()); + E_LookupAccess lookup_access = lookup_rule->access(arena, E_ExprKind_MemberAccess, lhs, rhs, &e_expr_nil, lookup_info.user_data); + result = lookup_access.irtree_and_type; +#endif + } + + //- rjf: error on failure-to-generate + if(!generated) + { + e_msgf(arena, &result.msgs, E_MsgKind_ResolutionFailure, expr->location, "`%S` could not be found.", string); + } + + scratch_end(scratch); + }break; + + //- rjf: leaf offsets + case E_ExprKind_LeafOffset: + { + E_IRNode *new_tree = e_push_irnode(arena, RDI_EvalOp_ConstU64); + new_tree->value = expr->value; + new_tree->space = expr->space; + result.root = new_tree; + result.type_key = expr->type_key; + result.mode = E_Mode_Offset; + }break; + + //- rjf: leaf values + case E_ExprKind_LeafValue: + { + E_IRNode *new_tree = e_push_irnode(arena, RDI_EvalOp_ConstU128); + new_tree->value = expr->value; + new_tree->space = expr->space; + result.root = new_tree; + result.type_key = expr->type_key; + result.mode = E_Mode_Value; + }break; + + //- rjf: leaf file paths + case E_ExprKind_LeafFilePath: + { + Temp scratch = scratch_begin(&arena, 1); + String8 file_path = expr->string; + FileProperties props = os_properties_from_file_path(file_path); + if(!str8_match(expr->qualifier, str8_lit("folder"), 0) && !(props.flags & FilePropertyFlag_IsFolder) && file_path.size != 0) + { + E_Space space = e_space_make(E_SpaceKind_FileSystem); + result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(file_path))); + result.type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("file")); + result.mode = E_Mode_Value; + } + else + { + String8 folder_path = str8_chop_last_slash(file_path); + props = os_properties_from_file_path(folder_path); + if(props.flags & FilePropertyFlag_IsFolder || folder_path.size == 0 || str8_match(folder_path, str8_lit("/"), StringMatchFlag_SlashInsensitive)) + { + E_Space space = e_space_make(E_SpaceKind_FileSystem); + result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, e_id_from_string(folder_path))); + result.type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("folder")); + result.mode = E_Mode_Value; + } + } + scratch_end(scratch); + }break; + + //- rjf: types + case E_ExprKind_TypeIdent: + { + result.root = e_irtree_const_u(arena, 0); + result.root->space = expr->space; + result.type_key = expr->type_key; + result.mode = E_Mode_Null; + }break; + + //- rjf: (unexpected) type expressions + case E_ExprKind_Ptr: + case E_ExprKind_Array: + case E_ExprKind_Func: + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Type expression not expected."); + }break; + + //- rjf: definitions + case E_ExprKind_Define: + { + E_Expr *lhs = expr->first; + E_Expr *rhs = lhs->next; + result = e_irtree_and_type_from_expr(arena, rhs); + if(lhs->kind != E_ExprKind_LeafIdentifier) + { + e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Left side of assignment must be an unused identifier."); + } + }break; + } + + //- rjf: if the evaluated type has a hook for an extra layer of ir generation, + // call into it + E_Type *type = e_type_from_key__cached(result.type_key); + if(type->irgen != 0) + { + result = type->irgen(arena, &result); + } + + //- rjf: find any auto hooks according to this generation's type { E_ExprList exprs = e_auto_hook_exprs_from_type_key__cached(result.type_key); for(E_ExprNode *n = exprs.first; n != 0; n = n->next) @@ -3301,6 +2894,8 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr) Task *task = push_array(scratch.arena, Task, 1); SLLQueuePush(first_task, last_task, task); task->expr = e; + task->parent_expr = expr; + task->parent_irtree_and_type = result; break; } } @@ -3308,7 +2903,9 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr) } } + ////////////////////////////// //- rjf: unpoison the tags we used + // for(Task *t = first_task; t != 0; t = t->next) { e_expr_unpoison(t->expr); @@ -3588,6 +3185,7 @@ e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_Type //////////////////////////////// //~ rjf: Expression & IR-Tree => Rules +#if 0 // TODO(rjf): @eval internal E_LookupRule * e_lookup_rule_from_type_key(E_TypeKey type_key) { @@ -3608,6 +3206,7 @@ e_lookup_rule_from_type_key(E_TypeKey type_key) return rule; } +#endif #if 0 // TODO(rjf): @eval internal E_LookupRuleExprPair diff --git a/src/eval/eval_ir.h b/src/eval/eval_ir.h index bb197c22..871527e2 100644 --- a/src/eval/eval_ir.h +++ b/src/eval/eval_ir.h @@ -134,8 +134,10 @@ struct E_IRCtx E_String2ExprMap *macro_map; // rjf: hook maps +#if 0 // TODO(rjf): @eval E_LookupRuleMap *lookup_rule_map; E_IRGenRuleMap *irgen_rule_map; +#endif E_AutoHookMap *auto_hook_map; }; @@ -164,6 +166,7 @@ struct E_IRState //////////////////////////////// //~ rjf: Globals +#if 0 // TODO(rjf): @eval local_persist read_only E_LookupRule e_lookup_rule__nil = { str8_lit_comp("nil"), @@ -187,6 +190,8 @@ local_persist read_only E_IRGenRule e_irgen_rule__default = str8_lit_comp("default"), E_IRGEN_FUNCTION_NAME(default), }; +#endif + global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil}; thread_static E_IRState *e_ir_state = 0; @@ -204,20 +209,24 @@ internal void e_select_ir_ctx(E_IRCtx *ctx); //////////////////////////////// //~ rjf: Lookups +#if 0 // TODO(rjf): @eval internal E_LookupRuleMap e_lookup_rule_map_make(Arena *arena, U64 slots_count); internal void e_lookup_rule_map_insert(Arena *arena, E_LookupRuleMap *map, E_LookupRule *rule); #define e_lookup_rule_map_insert_new(arena, map, name_, ...) e_lookup_rule_map_insert((arena), (map), &(E_LookupRule){.name = (name_), __VA_ARGS__}) internal E_LookupRule *e_lookup_rule_from_string(String8 string); +#endif //////////////////////////////// //~ rjf: IR Gen Rules +#if 0 // TODO(rjf): @eval internal E_IRGenRuleMap e_irgen_rule_map_make(Arena *arena, U64 slots_count); internal void e_irgen_rule_map_insert(Arena *arena, E_IRGenRuleMap *map, E_IRGenRule *rule); #define e_irgen_rule_map_insert_new(arena, map, name_, ...) e_irgen_rule_map_insert((arena), (map), &(E_IRGenRule){.name = (name_), __VA_ARGS__}) internal E_IRGenRule *e_irgen_rule_from_string(String8 string); +#endif //////////////////////////////// //~ rjf: Auto Hooks @@ -288,7 +297,9 @@ internal E_Expr *e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *r //////////////////////////////// //~ rjf: Expression & IR-Tree => Rules +#if 0 // TODO(rjf): @eval internal E_LookupRule *e_lookup_rule_from_type_key(E_TypeKey type_key); +#endif #if 0 // TODO(rjf): @eval internal E_LookupRuleExprPair e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree); diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index ee2944e9..69d66116 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -396,6 +396,11 @@ e_type_key_cons_(E_ConsTypeParams *params) node->key = key; MemoryCopyStruct(&node->params, params); node->params.name = push_str8_copy(e_type_state->arena, params->name); + if(node->params.expand.info != 0) + { + if(node->params.expand.id_from_num == 0) {node->params.expand.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity);} + if(node->params.expand.num_from_id == 0) {node->params.expand.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity);} + } if(params->members != 0) { node->params.members = push_array(e_type_state->arena, E_Member, params->count); @@ -632,11 +637,9 @@ e_type_from_key(Arena *arena, E_TypeKey key) type->count = node->params.count; type->depth = node->params.depth; type->arch = node->params.arch; + type->irgen = node->params.irgen; type->access = node->params.access; - type->expand_info = node->params.expand_info; - type->expand_range = node->params.expand_range; - type->expand_id_from_num = node->params.expand_id_from_num; - type->expand_num_from_id = node->params.expand_num_from_id; + type->expand = node->params.expand; type->byte_size = node->byte_size; switch(type->kind) { @@ -2067,3 +2070,447 @@ e_type_member_from_key_name__cached(E_TypeKey key, String8 name) } return result; } + +//////////////////////////////// +//~ rjf: (Built-In Type Hooks) Default Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(default) +{ + E_TypeExpandInfo result = {0}; + { + E_TypeKey type_key = e_type_unwrap(irtree->type_key); + E_TypeKind type_kind = e_type_kind_from_key(type_key); + if(e_type_kind_is_pointer_or_ref(type_kind)) + { + E_Type *type = e_type_from_key__cached(type_key); + result.expr_count = type->count; + if(type->count == 1) + { + 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); + if(direct_type_kind == E_TypeKind_Struct || + direct_type_kind == E_TypeKind_Class || + direct_type_kind == E_TypeKind_Union) + { + E_MemberArray data_members = e_type_data_members_from_key_filter__cached(direct_type_key, filter); + result.expr_count = data_members.count; + } + else if(direct_type_kind == E_TypeKind_Enum) + { + E_Type *direct_type = e_type_from_key__cached(direct_type_key); + result.expr_count = direct_type->count; + } + } + } + else if(type_kind == E_TypeKind_Struct || + type_kind == E_TypeKind_Class || + type_kind == E_TypeKind_Union) + { + E_MemberArray data_members = e_type_data_members_from_key_filter__cached(type_key, filter); + result.expr_count = data_members.count; + } + else if(type_kind == E_TypeKind_Enum) + { + E_Type *direct_type = e_type_from_key__cached(type_key); + result.expr_count = direct_type->count; + } + else if(type_kind == E_TypeKind_Array) + { + E_Type *type = e_type_from_key__cached(type_key); + result.expr_count = type->count; + } + } + return result; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default) +{ + Temp scratch = scratch_begin(&arena, 1); + { + //- rjf: unpack type of expression + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(scratch.arena, expr); + E_TypeKey lhs_type_key = lhs_irtree.type_key; + E_TypeKind lhs_type_kind = e_type_kind_from_key(lhs_type_key); + E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(lhs_type_key)); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); + + //- rjf: pull out specific kinds of types + B32 do_struct_range = 0; + B32 do_enum_range = 0; + B32 do_index_range = 0; + E_TypeKey enum_type_key = zero_struct; + E_TypeKey struct_type_key = zero_struct; + E_TypeKind struct_type_kind = E_TypeKind_Null; + if(e_type_kind_is_pointer_or_ref(lhs_type_kind)) + { + E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); + if(lhs_type->count == 1 && + (direct_type_kind == E_TypeKind_Struct || + direct_type_kind == E_TypeKind_Union || + direct_type_kind == E_TypeKind_Class)) + { + struct_type_key = direct_type_key; + struct_type_kind = direct_type_kind; + do_struct_range = 1; + } + else if(lhs_type->count == 1 && direct_type_kind == E_TypeKind_Enum) + { + do_enum_range = 1; + enum_type_key = direct_type_key; + } + else + { + do_index_range = 1; + } + } + else if(lhs_type_kind == E_TypeKind_Struct || + lhs_type_kind == E_TypeKind_Union || + lhs_type_kind == E_TypeKind_Class) + { + struct_type_key = lhs_type_key; + struct_type_kind = lhs_type_kind; + do_struct_range = 1; + } + else if(lhs_type_kind == E_TypeKind_Enum) + { + enum_type_key = lhs_type_key; + do_enum_range = 1; + } + else if(lhs_type_kind == E_TypeKind_Set) + { + do_index_range = 1; + } + else if(lhs_type_kind == E_TypeKind_Array) + { + do_index_range = 1; + } + + //- rjf: struct case -> the lookup-range will return a range of members + if(do_struct_range) + { + E_MemberArray data_members = e_type_data_members_from_key_filter__cached(struct_type_key, filter); + Rng1U64 legal_idx_range = r1u64(0, data_members.count); + Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); + U64 read_range_count = dim_1u64(read_range); + for(U64 idx = 0; idx < read_range_count; idx += 1) + { + U64 member_idx = idx + read_range.min; + String8 member_name = data_members.v[member_idx].name; + exprs_out[idx] = e_expr_irext_member_access(arena, expr, &lhs_irtree, member_name); + } + } + + //- rjf: enum case -> the lookup-range will return a range of enum constants + else if(do_enum_range) + { + E_Type *type = e_type_from_key__cached(enum_type_key); + Rng1U64 legal_idx_range = r1u64(0, type->count); + Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); + U64 read_range_count = dim_1u64(read_range); + for(U64 idx = 0; idx < read_range_count; idx += 1) + { + U64 member_idx = idx + read_range.min; + String8 member_name = type->enum_vals[member_idx].name; + exprs_out[idx] = e_expr_irext_member_access(arena, expr, &lhs_irtree, member_name); + } + } + + //- rjf: ptr case -> the lookup-range will return a range of dereferences + else if(do_index_range) + { + U64 read_range_count = dim_1u64(idx_range); + for(U64 idx = 0; idx < read_range_count; idx += 1) + { + exprs_out[idx] = e_expr_irext_array_index(arena, expr, &lhs_irtree, idx_range.min + idx); + } + } + } + scratch_end(scratch); +} + +E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity) +{ + return num; +} + +E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity) +{ + return id; +} + +//////////////////////////////// +//~ rjf: (Built-In Type Hooks) `folder` type + +typedef struct E_FolderAccel E_FolderAccel; +struct E_FolderAccel +{ + String8 folder_path; + String8Array folders; + String8Array files; +}; + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(folder) +{ + E_TypeExpandInfo info = {0}; + { + Temp scratch = scratch_begin(&arena, 1); + + //- rjf: evaluate lhs file path ID + E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, irtree->root); + String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); + E_Interpretation lhs_interp = e_interpret(lhs_bytecode); + E_Value lhs_value = lhs_interp.value; + U64 lhs_string_id = lhs_value.u64; + String8 folder_path = e_string_from_id(lhs_string_id); + + //- rjf: compute filter - omit common prefixes (common parent paths) + String8 local_filter = filter; + { + U64 folder_pos_in_filter = str8_find_needle(filter, 0, folder_path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); + if(folder_pos_in_filter < filter.size) + { + local_filter = str8_skip(local_filter, folder_pos_in_filter+folder_path.size); + local_filter = str8_skip_chop_slashes(local_filter); + } + else + { + MemoryZeroStruct(&local_filter); + } + } + + //- rjf: gather & filter files in this folder + String8List folder_paths = {0}; + String8List file_paths = {0}; + { + OS_FileIter *iter = os_file_iter_begin(scratch.arena, folder_path, 0); + for(OS_FileInfo info = {0}; os_file_iter_next(scratch.arena, iter, &info);) + { + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, local_filter, info.name); + if(matches.count == matches.needle_part_count) + { + if(info.props.flags & FilePropertyFlag_IsFolder) + { + str8_list_push(scratch.arena, &folder_paths, push_str8_copy(arena, info.name)); + } + else + { + str8_list_push(scratch.arena, &file_paths, push_str8_copy(arena, info.name)); + } + } + } + os_file_iter_end(iter); + } + + //- rjf: build accelerator + E_FolderAccel *accel = push_array(arena, E_FolderAccel, 1); + accel->folder_path = push_str8_copy(arena, folder_path); + accel->folders = str8_array_from_list(arena, &folder_paths); + accel->files = str8_array_from_list(arena, &file_paths); + info.user_data = accel; + info.expr_count = accel->folders.count + accel->files.count; + scratch_end(scratch); + } + return info; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(folder) +{ + E_FolderAccel *accel = (E_FolderAccel *)user_data; + U64 out_idx = 0; + for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) + { + Temp scratch = scratch_begin(&arena, 1); + E_Expr *expr = &e_expr_nil; + String8 expr_string = {0}; + if(0 <= idx && idx < accel->folders.count) + { + String8 folder_name = accel->folders.v[idx - 0]; + String8 folder_path = push_str8f(scratch.arena, "%S%s%S", accel->folder_path, accel->folder_path.size != 0 ? "/" : "", folder_name); + expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); + expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("folder")); + expr->space = e_space_make(E_SpaceKind_FileSystem); + expr->value.u64 = e_id_from_string(folder_path); + expr_string = push_str8f(arena, "\"%S\"", escaped_from_raw_str8(scratch.arena, folder_name)); + } + else if(accel->folders.count <= idx && idx < accel->folders.count + accel->files.count) + { + String8 file_name = accel->files.v[idx - accel->folders.count]; + String8 file_path = push_str8f(scratch.arena, "%S%s%S", accel->folder_path, accel->folder_path.size != 0 ? "/" : "", file_name); + expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); + expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("file")); + expr->space = e_space_make(E_SpaceKind_FileSystem); + expr->value.u64 = e_id_from_string(file_path); + expr_string = push_str8f(arena, "\"%S\"", escaped_from_raw_str8(scratch.arena, file_name)); + } + exprs_out[out_idx] = expr; + exprs_strings_out[out_idx] = expr_string; + scratch_end(scratch); + } +} + +E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(folder) +{ + U64 id = 0; + E_FolderAccel *accel = (E_FolderAccel *)user_data; + String8 name = {0}; + if(0 < num && num <= accel->folders.count) + { + name = accel->folders.v[num-1]; + } + else if(accel->folders.count < num && num <= accel->folders.count+accel->files.count) + { + name = accel->files.v[num-accel->folders.count-1]; + } + id = e_hash_from_string(5381, name); + return id; +} + +E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(folder) +{ + U64 num = 0; + E_FolderAccel *accel = (E_FolderAccel *)user_data; + for(U64 idx = 0; idx < accel->folders.count+accel->files.count; idx += 1) + { + String8 name = {0}; + if(0 <= idx && idx < accel->folders.count) + { + name = accel->folders.v[idx]; + } + else if(accel->folders.count <= idx && idx < accel->folders.count+accel->files.count) + { + name = accel->files.v[idx-accel->folders.count]; + } + U64 hash = e_hash_from_string(5381, name); + if(hash == id) + { + num = idx+1; + break; + } + } + return num; +} + +//////////////////////////////// +//~ rjf: (Built-In Type Hooks) `file` type + +typedef struct E_FileAccel E_FileAccel; +struct E_FileAccel +{ + String8 file_path; + FileProperties props; + String8Array fields; +}; + +E_TYPE_IRGEN_FUNCTION_DEF(file) +{ + E_IRTreeAndType result = *irtree; + E_FileAccel *accel = push_array(arena, E_FileAccel, 1); + { + Temp scratch = scratch_begin(&arena, 1); + + //- rjf: evaluate lhs file path ID + E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, irtree->root); + String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); + E_Interpretation lhs_interp = e_interpret(lhs_bytecode); + E_Value lhs_value = lhs_interp.value; + U64 lhs_string_id = lhs_value.u64; + + //- rjf: get file path + String8 file_path = e_string_from_id(lhs_string_id); + + //- rjf: build field list + String8List fields = {0}; + str8_list_pushf(arena, &fields, "size"); + str8_list_pushf(arena, &fields, "last_modified_time"); + str8_list_pushf(arena, &fields, "creation_time"); + str8_list_pushf(arena, &fields, "data"); + + //- rjf: fill accel + accel->file_path = push_str8_copy(arena, file_path); + accel->props = os_properties_from_file_path(file_path); + accel->fields = str8_array_from_list(arena, &fields); + + scratch_end(scratch); + } + result.user_data = accel; + return result; +} + +E_TYPE_ACCESS_FUNCTION_DEF(file) +{ + E_IRTreeAndType result = {&e_irnode_nil}; + E_FileAccel *accel = (E_FileAccel *)lhs_irtree->user_data; + if(expr->kind == E_ExprKind_MemberAccess) + { + E_Expr *rhs = expr->first->next; + String8 member_name = rhs->string; + if(str8_match(member_name, str8_lit("size"), 0)) + { + E_Space space = e_space_make(E_SpaceKind_FileSystem); + space.u64_0 = e_id_from_string(accel->file_path); + result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.size)); + result.type_key = e_type_key_basic(E_TypeKind_U64); + result.mode = E_Mode_Value; + } + else if(str8_match(member_name, str8_lit("last_modified_time"), 0)) + { + E_Space space = e_space_make(E_SpaceKind_FileSystem); + space.u64_0 = e_id_from_string(accel->file_path); + result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.modified)); + result.type_key = e_type_key_basic(E_TypeKind_U64); + result.mode = E_Mode_Value; + } + else if(str8_match(member_name, str8_lit("creation_time"), 0)) + { + E_Space space = e_space_make(E_SpaceKind_FileSystem); + space.u64_0 = e_id_from_string(accel->file_path); + result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, accel->props.created)); + result.type_key = e_type_key_basic(E_TypeKind_U64); + result.mode = E_Mode_Value; + } + else if(str8_match(member_name, str8_lit("data"), 0)) + { + E_Space space = e_space_make(E_SpaceKind_File); + space.u64_0 = e_id_from_string(accel->file_path); + result.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); + result.type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), accel->props.size, 0); + result.mode = E_Mode_Offset; + } + } + return result; +} + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(file) +{ + E_FileAccel *accel = push_array(arena, E_FileAccel, 1); + { + Temp scratch = scratch_begin(&arena, 1); + + scratch_end(scratch); + } + E_TypeExpandInfo info = {accel, accel->fields.count}; + return info; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(file) +{ + E_FileAccel *accel = (E_FileAccel *)user_data; + U64 out_idx = 0; + for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) + { + E_Expr *expr = &e_expr_nil; + String8 string = {0}; + if(0 <= idx && idx < accel->fields.count) + { + String8 name = accel->fields.v[idx]; + expr = e_push_expr(arena, E_ExprKind_MemberAccess, 0); + E_Expr *lhs = e_expr_ref(arena, expr); + E_Expr *rhs = e_push_expr(arena, E_ExprKind_LeafIdentifier, 0); + rhs->string = push_str8_copy(arena, name); + e_expr_push_child(expr, lhs); + e_expr_push_child(expr, rhs); + } + exprs_out[out_idx] = expr; + exprs_strings_out[out_idx] = string; + } +} diff --git a/src/eval/eval_types.h b/src/eval/eval_types.h index 9c94c2e8..d57d3e37 100644 --- a/src/eval/eval_types.h +++ b/src/eval/eval_types.h @@ -47,11 +47,9 @@ struct E_ConsTypeParams E_Member *members; E_EnumVal *enum_vals; E_Expr **args; + E_TypeIRGenFunctionType *irgen; E_TypeAccessFunctionType *access; - E_TypeExpandInfoFunctionType *expand_info; - E_TypeExpandRangeFunctionType *expand_range; - E_TypeExpandIDFromNumFunctionType *expand_id_from_num; - E_TypeExpandNumFromIDFunctionType *expand_num_from_id; + E_TypeExpandRule expand; }; typedef struct E_ConsTypeNode E_ConsTypeNode; @@ -180,6 +178,17 @@ struct E_TypeState global read_only E_Member e_member_nil = {E_MemberKind_Null}; global read_only E_Type e_type_nil = {E_TypeKind_Null}; +E_TYPE_EXPAND_INFO_FUNCTION_DEF(default); +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default); +E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(identity); +E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity); +global read_only E_TypeExpandRule e_type_expand_rule__default = +{ + E_TYPE_EXPAND_INFO_FUNCTION_NAME(default), + E_TYPE_EXPAND_RANGE_FUNCTION_NAME(default), + E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(identity), + E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(identity), +}; thread_static E_TypeState *e_type_state = 0; //////////////////////////////// diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index 41c957ba..d94cd5cb 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -535,7 +535,7 @@ ev_keyed_expr_push_tags(Arena *arena, EV_View *view, EV_Block *block, EV_Key key //~ rjf: Block Building internal EV_BlockTree -ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChain exprs) +ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, E_Expr *expr) { ProfBeginFunction(); EV_BlockTree tree = {&ev_nil_block}; @@ -545,7 +545,7 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai //- rjf: generate root expression EV_Key root_key = ev_key_root(); EV_Key root_row_key = ev_key_make(ev_hash_from_key(root_key), 1); - E_Expr *root_expr = e_expr_copy(arena, exprs.last); + E_Expr *root_expr = e_expr_copy(arena, expr); #if 0 // TODO(rjf): @eval ev_keyed_expr_push_tags(arena, view, &ev_nil_block, root_row_key, root_expr); #endif @@ -555,7 +555,7 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai MemoryCopyStruct(tree.root, &ev_nil_block); tree.root->key = root_key; tree.root->string = str8_zero(); - tree.root->expr = root_expr; + tree.root->eval = e_eval_from_expr(arena, root_expr); tree.root->row_count = 1; tree.total_row_count += 1; tree.total_item_count += 1; @@ -566,12 +566,12 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai { Task *next; EV_Block *parent_block; - E_Expr *expr; + E_Eval eval; U64 child_id; U64 split_relative_idx; B32 default_expanded; }; - Task start_task = {0, tree.root, tree.root->expr, 1, 0}; + Task start_task = {0, tree.root, tree.root->eval, 1, 0}; Task *first_task = &start_task; Task *last_task = first_task; for(Task *t = first_task; t != 0; t = t->next) @@ -593,39 +593,41 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai continue; } - // rjf: unpack expr - E_IRTreeAndType expr_irtree = e_irtree_and_type_from_expr(scratch.arena, t->expr); + // rjf: unpack eval + E_Mode mode = t->eval.irtree.mode; + E_TypeKey type_key = t->eval.irtree.type_key; + E_Type *type = e_type_from_key__cached(type_key); + E_TypeExpandRule *type_expand_rule = &e_type_expand_rule__default; + if(type->expand.info != 0) + { + type_expand_rule = &type->expand; + } - // rjf: get expr's expansion rule + // rjf: get eval's visualization expansion rule // TODO(rjf): @eval EV_ExpandRuleTagPair expand_rule_and_tag = ev_expand_rule_tag_pair_from_expr_irtree(t->expr, &expr_irtree); - EV_ExpandRule *expand_rule = &ev_nil_expand_rule; - E_Expr *expand_rule_tag = &e_expr_nil; + EV_ExpandRule *viz_expand_rule = &ev_nil_expand_rule; + E_Expr *viz_expand_rule_tag = &e_expr_nil; // rjf: skip if no expansion rule, & type info disallows expansion - if(expand_rule == &ev_nil_expand_rule && !ev_type_key_and_mode_is_expandable(expr_irtree.type_key, expr_irtree.mode)) + if(viz_expand_rule == &ev_nil_expand_rule && !ev_type_key_and_mode_is_expandable(type_key, mode)) { continue; } - // rjf: get expr's lookup rule - // TODO(rjf): @eval E_LookupRuleExprPair lookup_rule_and_tag = &e_lookup_rule_tag_pair_from_expr_irtree(t->expr, &expr_irtree); - E_LookupRule *lookup_rule = e_lookup_rule_from_type_key(expr_irtree.type_key); - E_Expr *lookup_rule_tag = &e_expr_nil; - // rjf: get top-level lookup/expansion info - E_LookupInfo lookup_info = lookup_rule->info(arena, &expr_irtree, lookup_rule_tag, filter); - EV_ExpandInfo expand_info = expand_rule->info(arena, view, filter, t->expr, expand_rule_tag); + E_TypeExpandInfo type_expand_info = type_expand_rule->info(arena, &t->eval.irtree, filter); + EV_ExpandInfo viz_expand_info = viz_expand_rule->info(arena, view, filter, t->eval.expr, viz_expand_rule_tag); // rjf: determine expansion info - U64 expansion_row_count = lookup_info.named_expr_count ? lookup_info.named_expr_count : lookup_info.idxed_expr_count; - if(expand_rule != &ev_nil_expand_rule) + U64 expansion_row_count = type_expand_info.expr_count; + if(viz_expand_rule != &ev_nil_expand_rule) { - expansion_row_count = expand_info.row_count; + expansion_row_count = viz_expand_info.row_count; } // rjf: determine if this expansion supports child expansions B32 allow_child_expansions = 1; - if(expand_info.single_item) + if(viz_expand_info.single_item) { // NOTE(rjf): for now, just plugging in the heuristic of "is this a single row (a.k.a. visualizer)?" allow_child_expansions = 0; @@ -641,25 +643,21 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai expansion_block->parent = t->parent_block; expansion_block->key = key; expansion_block->split_relative_idx = t->split_relative_idx; - expansion_block->expr = t->expr; - expansion_block->lookup_tag = lookup_rule_tag; - expansion_block->expand_tag = expand_rule_tag; - expansion_block->lookup_rule = lookup_rule; - expansion_block->expand_rule = expand_rule; - expansion_block->lookup_rule_user_data = lookup_info.user_data; - expansion_block->expand_rule_user_data = expand_info.user_data; + expansion_block->eval = t->eval; + expansion_block->type_expand_info = type_expand_info; + expansion_block->type_expand_rule = type_expand_rule; + expansion_block->viz_expand_info = viz_expand_info; + expansion_block->viz_expand_rule = viz_expand_rule; expansion_block->row_count = expansion_row_count; - expansion_block->single_item = expand_info.single_item; - expansion_block->rows_default_expanded = expand_info.rows_default_expanded; tree.total_row_count += expansion_row_count; - tree.total_item_count += expand_info.single_item ? 1 : expansion_row_count; + tree.total_item_count += viz_expand_info.single_item ? 1 : expansion_row_count; } // rjf: gather children expansions from expansion state U64 child_count = 0; EV_Key *child_keys = 0; U64 *child_nums = 0; - if(allow_child_expansions && !child_count && !expand_info.rows_default_expanded && expand_node != 0 && expansion_row_count != 0) + if(allow_child_expansions && !child_count && !viz_expand_info.rows_default_expanded && expand_node != 0 && expansion_row_count != 0) { // rjf: count children for(EV_ExpandNode *child = expand_node->first; child != 0; child = child->next, child_count += 1){} @@ -673,7 +671,7 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai for(EV_ExpandNode *child = expand_node->first; child != 0; child = child->next, idx += 1) { child_keys[idx] = child->key; - child_nums[idx] = lookup_rule->num_from_id(child->key.child_id, lookup_info.user_data); + child_nums[idx] = type_expand_rule->num_from_id(type_expand_info.user_data, child->key.child_id); if(child_nums[idx] != child_keys[idx].child_id) { needs_sort = 1; @@ -706,14 +704,14 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai } // rjf: gather children expansions from inverse of expansion state - if(allow_child_expansions && !child_count && (expand_info.rows_default_expanded || (expand_node == 0 && !expand_info.rows_default_expanded))) + if(allow_child_expansions && !child_count && (viz_expand_info.rows_default_expanded || (expand_node == 0 && !viz_expand_info.rows_default_expanded))) { - child_count = expand_info.row_count; + child_count = viz_expand_info.row_count; child_keys = push_array(scratch.arena, EV_Key, child_count); child_nums = push_array(scratch.arena, U64, child_count); for(U64 idx = 0; idx < child_count; idx += 1) { - U64 child_id = lookup_rule->id_from_num(idx+1, lookup_info.user_data); + U64 child_id = type_expand_rule->id_from_num(type_expand_info.user_data, idx+1); child_keys[idx] = ev_key_make(ev_hash_from_key(key), child_id); child_nums[idx] = idx+1; } @@ -728,14 +726,15 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai { continue; } - if(expand_info.rows_default_expanded || ev_expansion_from_key(view, child_keys[idx])) + if(viz_expand_info.rows_default_expanded || ev_expansion_from_key(view, child_keys[idx])) { Rng1U64 child_range = r1u64(split_relative_idx, split_relative_idx+1); E_Expr *child_expr = &e_expr_nil; String8 child_string = {0}; - lookup_rule->range(arena, t->expr, lookup_rule_tag, filter, r1u64(split_relative_idx, split_relative_idx+1), &child_expr, &child_string, lookup_info.user_data); + type_expand_rule->range(arena, type_expand_info.user_data, t->eval.expr, filter, r1u64(split_relative_idx, split_relative_idx+1), &child_expr, &child_string); if(child_expr != &e_expr_nil) { + E_Eval child_eval = e_eval_from_expr(arena, child_expr); EV_Key child_key = child_keys[idx]; #if 0 // TODO(rjf): @eval ev_keyed_expr_push_tags(arena, view, expansion_block, child_key, child_expr); @@ -743,10 +742,10 @@ ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChai Task *task = push_array(scratch.arena, Task, 1); SLLQueuePush(first_task, last_task, task); task->parent_block = expansion_block; - task->expr = child_expr; + task->eval = child_eval; task->child_id = child_key.child_id; task->split_relative_idx = split_relative_idx; - task->default_expanded = expand_info.rows_default_expanded; + task->default_expanded = viz_expand_info.rows_default_expanded; } } } @@ -771,6 +770,20 @@ ev_depth_from_block(EV_Block *block) //////////////////////////////// //~ rjf: Block Coordinate Spaces +internal U64 +ev_block_id_from_num(EV_Block *block, U64 num) +{ + U64 result = block->type_expand_rule->id_from_num(block->type_expand_info.user_data, num); + return result; +} + +internal U64 +ev_block_num_from_id(EV_Block *block, U64 id) +{ + U64 result = block->type_expand_rule->num_from_id(block->type_expand_info.user_data, id); + return result; +} + internal EV_BlockRangeList ev_block_range_list_from_tree(Arena *arena, EV_BlockTree *block_tree) { @@ -870,7 +883,7 @@ ev_key_from_num(EV_BlockRangeList *block_ranges, U64 num) if(contains_1u64(global_range, num)) { U64 relative_num = (num - base_num) + n->v.range.min + 1; - U64 child_id = n->v.block->lookup_rule->id_from_num(relative_num, n->v.block->lookup_rule_user_data); + U64 child_id = ev_block_id_from_num(n->v.block, relative_num); EV_Key block_key = n->v.block->key; key = ev_key_make(ev_hash_from_key(block_key), child_id); break; @@ -890,7 +903,7 @@ ev_num_from_key(EV_BlockRangeList *block_ranges, EV_Key key) U64 hash = ev_hash_from_key(n->v.block->key); if(hash == key.parent_hash) { - U64 relative_num = n->v.block->lookup_rule->num_from_id(key.child_id, n->v.block->lookup_rule_user_data); + U64 relative_num = ev_block_num_from_id(n->v.block, key.child_id); Rng1U64 num_range = r1u64(n->v.range.min, n->v.block->single_item ? (n->v.range.min+1) : n->v.range.max); if(contains_1u64(num_range, relative_num-1)) { @@ -1011,7 +1024,7 @@ ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8 if(block_relative_range__windowed.max > block_relative_range__windowed.min) { // rjf: get info about expansion range - B32 is_root = 0; + B32 is_standalone_row = 0; U64 range_exprs_count = dim_1u64(block_relative_range__windowed); E_Expr **range_exprs = push_array(arena, E_Expr *, range_exprs_count); String8 *range_exprs_strings = push_array(arena, String8 ,range_exprs_count); @@ -1019,18 +1032,17 @@ ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8 { range_exprs[idx] = &e_expr_nil; } - if(n->v.block->lookup_rule == &e_lookup_rule__nil || - n->v.block->single_item) + if(n->v.block->single_item) { - is_root = 1; + is_standalone_row = 1; } else { - n->v.block->lookup_rule->range(arena, n->v.block->expr, n->v.block->lookup_tag, filter, block_relative_range__windowed, range_exprs, range_exprs_strings, n->v.block->lookup_rule_user_data); + n->v.block->type_expand_rule->range(arena, n->v.block->type_expand_info.user_data, n->v.block->eval.expr, filter, block_relative_range__windowed, range_exprs, range_exprs_strings); } // rjf: no expansion operator applied -> push row for block expression; pass through block info - if(is_root) + if(is_standalone_row) { EV_WindowedRowNode *row_node = push_array(arena, EV_WindowedRowNode, 1); SLLQueuePush(rows.first, rows.last, row_node); @@ -1042,16 +1054,17 @@ ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8 row->key = ev_key_make(ev_hash_from_key(row->block->key), 1); row->visual_size = n->v.block->single_item ? (n->v.block->row_count - (num_skipped + num_chopped)) : 1; row->string = n->v.block->string; - row->expr = n->v.block->expr; + row->eval = n->v.block->eval; } // rjf: expansion operator applied -> call, and add rows for all expressions in the viewable range else for EachIndex(idx, range_exprs_count) { U64 child_num = block_relative_range.min + num_skipped + idx + 1; - U64 child_id = n->v.block->lookup_rule->id_from_num(child_num, n->v.block->lookup_rule_user_data); + U64 child_id = ev_block_id_from_num(n->v.block, child_num); EV_Key row_key = ev_key_make(ev_hash_from_key(n->v.block->key), child_id); E_Expr *row_expr = range_exprs[idx]; + E_Eval row_eval = e_eval_from_expr(arena, row_expr); #if 0 // TODO(rjf): @eval ev_keyed_expr_push_tags(arena, view, n->v.block, row_key, row_expr); #endif @@ -1063,7 +1076,7 @@ ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8 row->key = row_key; row->visual_size = 1; row->string = range_exprs_strings[idx]; - row->expr = row_expr; + row->eval = row_eval; } } } @@ -1085,7 +1098,7 @@ ev_row_from_num(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList * { result = push_array(arena, EV_Row, 1); result->block = &ev_nil_block; - result->expr = &e_expr_nil; + result->eval = e_eval_nil; } return result; } @@ -1098,54 +1111,13 @@ ev_rows_from_num_range(Arena *arena, EV_View *view, String8 filter, EV_BlockRang return rows; } -internal String8 -ev_expr_string_from_row(Arena *arena, EV_Row *row, EV_StringFlags flags) -{ - String8 result = row->string; - E_Expr *notable_expr = row->expr; - for(B32 good = 0; !good;) - { - switch(notable_expr->kind) - { - default:{good = 1;}break; - case E_ExprKind_Address: - case E_ExprKind_Deref: - case E_ExprKind_Cast: - { - notable_expr = notable_expr->last; - }break; - case E_ExprKind_Ref: - { - notable_expr = notable_expr->ref; - }break; - } - } - if(result.size == 0) switch(notable_expr->kind) - { - default: - { - result = e_string_from_expr(arena, notable_expr); - }break; - case E_ExprKind_ArrayIndex: - { - result = push_str8f(arena, "[%S]", e_string_from_expr(arena, notable_expr->last)); - }break; - case E_ExprKind_MemberAccess: - { - result = push_str8f(arena, ".%S", e_string_from_expr(arena, notable_expr->last)); - }break; - } - return result; -} - internal B32 ev_row_is_expandable(EV_Row *row) { B32 result = 0; if(!ev_key_match(ev_key_root(), row->block->key)) { - Temp scratch = scratch_begin(0, 0); - E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, row->expr); + E_IRTreeAndType irtree = row->eval.irtree; // rjf: determine if view rules force expandability if(!result) @@ -1162,10 +1134,8 @@ ev_row_is_expandable(EV_Row *row) // rjf: determine if type info force expandability if(!result) { - E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, row->expr); result = ev_type_key_and_mode_is_expandable(irtree.type_key, irtree.mode); } - scratch_end(scratch); } return result; } @@ -1174,10 +1144,8 @@ internal B32 ev_row_is_editable(EV_Row *row) { B32 result = 0; - Temp scratch = scratch_begin(0, 0); - E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, row->expr); + E_IRTreeAndType irtree = row->eval.irtree; result = ev_type_key_is_editable(irtree.type_key); - scratch_end(scratch); return result; } @@ -1826,7 +1794,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string) // rjf: single-length pointers -> just gen new task for deref'd expr if(ptr_data->type->count == 1) { - E_Expr *deref_expr = e_expr_irext_deref(arena, eval.exprs.first, &eval.irtree); + E_Expr *deref_expr = e_expr_irext_deref(arena, eval.expr, &eval.irtree); E_Eval deref_eval = e_eval_from_expr(arena, deref_expr); need_new_task = 1; new_task.params = *params; diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index 214fe7a5..7f5115d0 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -146,15 +146,13 @@ struct EV_Block // rjf: split index, relative to parent's space U64 split_relative_idx; - // rjf: expression / visualization info - String8 string; - E_Expr *expr; - E_Expr *lookup_tag; - E_Expr *expand_tag; - E_LookupRule *lookup_rule; - EV_ExpandRule *expand_rule; - void *lookup_rule_user_data; - void *expand_rule_user_data; + // rjf: evaluation info + String8 string; + E_Eval eval; + E_TypeExpandInfo type_expand_info; + E_TypeExpandRule *type_expand_rule; + EV_ExpandInfo viz_expand_info; + EV_ExpandRule *viz_expand_rule; // rjf: expansion info U64 row_count; @@ -201,8 +199,8 @@ struct EV_Row EV_Block *block; EV_Key key; U64 visual_size; - String8 string; - E_Expr *expr; + String8 string; + E_Eval eval; }; typedef struct EV_WindowedRowNode EV_WindowedRowNode; @@ -282,7 +280,7 @@ global read_only EV_ExpandRule ev_nil_expand_rule = EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), }; thread_static EV_ExpandRuleTable *ev_view_rule_info_table = 0; -global read_only EV_Block ev_nil_block = {&ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, {0}, 0, {0}, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_lookup_rule__nil, &ev_nil_expand_rule}; +global read_only EV_Block ev_nil_block = {&ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, &ev_nil_block, {0}, 0, {0}, {zero_struct, zero_struct, &e_expr_nil, &e_irnode_nil}}; //////////////////////////////// //~ rjf: Key Functions @@ -340,12 +338,14 @@ internal void ev_keyed_expr_push_tags(Arena *arena, EV_View *view, EV_Block *blo //////////////////////////////// //~ rjf: Block Building -internal EV_BlockTree ev_block_tree_from_exprs(Arena *arena, EV_View *view, String8 filter, E_ExprChain exprs); +internal EV_BlockTree ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, E_Expr *expr); internal U64 ev_depth_from_block(EV_Block *block); //////////////////////////////// //~ rjf: Block Coordinate Spaces - + +internal U64 ev_block_id_from_num(EV_Block *block, U64 num); +internal U64 ev_block_num_from_id(EV_Block *block, U64 id); internal EV_BlockRangeList ev_block_range_list_from_tree(Arena *arena, EV_BlockTree *block_tree); internal EV_BlockRange ev_block_range_from_num(EV_BlockRangeList *block_ranges, U64 num); internal EV_Key ev_key_from_num(EV_BlockRangeList *block_ranges, U64 num); @@ -359,7 +359,6 @@ internal U64 ev_num_from_vnum(EV_BlockRangeList *block_ranges, U64 vidx); internal EV_WindowedRowList ev_windowed_row_list_from_block_range_list(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList *block_ranges, Rng1U64 vnum_range); internal EV_Row *ev_row_from_num(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList *block_ranges, U64 num); internal EV_WindowedRowList ev_rows_from_num_range(Arena *arena, EV_View *view, String8 filter, EV_BlockRangeList *block_ranges, Rng1U64 num_range); -internal String8 ev_expr_string_from_row(Arena *arena, EV_Row *row, EV_StringFlags flags); internal B32 ev_row_is_expandable(EV_Row *row); internal B32 ev_row_is_editable(EV_Row *row); diff --git a/src/lib_raddbg_markup/raddbg_markup.h b/src/lib_raddbg_markup/raddbg_markup.h index a141fa53..e153ab4d 100644 --- a/src/lib_raddbg_markup/raddbg_markup.h +++ b/src/lib_raddbg_markup/raddbg_markup.h @@ -37,8 +37,8 @@ # define raddbg_watch(fmt, ...) raddbg_watch__impl((fmt), __VA_ARGS__) # define raddbg_pin(expr, ...) /* NOTE(rjf): inspected by debugger ui - does not change program execution */ # define raddbg_log(fmt, ...) raddbg_log__impl((fmt), __VA_ARGS__) -# define raddbg_entry_point(...) raddbg_exe_data static char raddbg_gen_data_id()[] = ("entry_point: " #__VA_ARGS__) -# define raddbg_auto_view_rule(type, ...) raddbg_exe_data static char raddbg_gen_data_id()()[] = ("auto_view_rule: {type: \"" #type "\", view_rule: \"" #__VA_ARGS__ "\"}") +# define raddbg_entry_point(...) raddbg_exe_data static char raddbg_gen_data_id()[] = ("entry_point: \"" #__VA_ARGS__ "\"") +# define raddbg_auto_view_rule(type, ...) raddbg_exe_data static char raddbg_gen_data_id()[] = ("auto_view_rule: {type: \"" #type "\", view_rule: \"" #__VA_ARGS__ "\"}") #endif //////////////////////////////// diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index af904043..ed46e37b 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -9,1275 +9,6 @@ #include "generated/raddbg.meta.c" -//////////////////////////////// -//~ rjf: Commands Eval Hooks - -E_LOOKUP_INFO_FUNCTION_DEF(commands) -{ - E_LookupInfo result = {0}; - if(filter.size != 0) - { - Temp scratch = scratch_begin(&arena, 1); - String8List cmd_names = {0}; - for EachNonZeroEnumVal(RD_CmdKind, k) - { - RD_CmdKindInfo *info = &rd_cmd_kind_info_table[k]; - String8 name = info->string; - FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, name); - if(matches.count == matches.needle_part_count) - { - str8_list_push(scratch.arena, &cmd_names, name); - } - } - String8Array *accel = push_array(arena, String8Array, 1); - *accel = str8_array_from_list(arena, &cmd_names); - result.user_data = accel; - result.idxed_expr_count = accel->count; - scratch_end(scratch); - } - else - { - result.idxed_expr_count = RD_CmdKind_COUNT; - } - return result; -} - -E_LOOKUP_ACCESS_FUNCTION_DEF(commands) -{ - E_LookupAccess result = {{&e_irnode_nil}}; - if(kind == E_ExprKind_MemberAccess) - { - String8 cmd_name = rhs->string; - result.irtree_and_type.type_key = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("command")); - result.irtree_and_type.mode = E_Mode_Value; - result.irtree_and_type.root = e_irtree_set_space(arena, e_space_make(RD_EvalSpaceKind_MetaCmd), e_irtree_const_u(arena, e_id_from_string(cmd_name))); - } - return result; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(commands) -{ - U64 out_idx = 0; - if(user_data != 0) - { - String8Array *accel = (String8Array *)user_data; - for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) - { - String8 cmd_name = accel->v[idx]; - E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); - expr->type_key = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("command")); - expr->space = e_space_make(RD_EvalSpaceKind_MetaCmd); - expr->value.u64 = e_id_from_string(cmd_name); - exprs[out_idx] = expr; - } - } - else - { - for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) - { - RD_CmdKind cmd_kind = (RD_CmdKind)idx; - String8 cmd_name = rd_cmd_kind_info_table[cmd_kind].string; - E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); - expr->type_key = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("command")); - expr->space = e_space_make(RD_EvalSpaceKind_MetaCmd); - expr->value.u64 = e_id_from_string(cmd_name); - exprs[out_idx] = expr; - } - } -} - -//////////////////////////////// -//~ rjf: Watches Eval Hooks - -E_LOOKUP_INFO_FUNCTION_DEF(watches) -{ - E_LookupInfo result = {0}; - Temp scratch = scratch_begin(&arena, 1); - { - RD_CfgList cfgs_list = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("watch")); - RD_CfgList cfgs_list__filtered = cfgs_list; - if(filter.size != 0) - { - MemoryZeroStruct(&cfgs_list__filtered); - for(RD_CfgNode *n = cfgs_list.first; n != 0; n = n->next) - { - String8 expr = rd_expr_from_cfg(n->v); - B32 passes_filter = 1; - if(filter.size != 0) - { - E_Eval eval = e_eval_from_string(scratch.arena, expr); - E_Type *type = e_type_from_key__cached(eval.irtree.type_key); - if(type->kind != E_TypeKind_Set) - { - passes_filter = 0; - FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, expr); - if(matches.count == matches.needle_part_count) - { - passes_filter = 1; - } - } - } - if(passes_filter) - { - rd_cfg_list_push(scratch.arena, &cfgs_list__filtered, n->v); - } - } - } - RD_CfgArray *cfgs = push_array(arena, RD_CfgArray, 1); - cfgs[0] = rd_cfg_array_from_list(arena, &cfgs_list__filtered); - result.user_data = cfgs; - result.idxed_expr_count = cfgs->count + 1; - } - scratch_end(scratch); - return result; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(watches) -{ - RD_CfgArray *cfgs = (RD_CfgArray *)user_data; - Rng1U64 legal_idx_range = r1u64(0, cfgs->count); - Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); - U64 read_range_count = dim_1u64(read_range); - for(U64 idx = 0; idx < read_range_count; idx += 1) - { - U64 cfg_idx = read_range.min + idx; - if(cfg_idx < cfgs->count) - { - String8 expr_string = rd_cfg_child_from_string(cfgs->v[cfg_idx], str8_lit("expression"))->first->string; - exprs[idx] = e_parse_expr_from_text(arena, expr_string).exprs.first; - exprs_strings[idx] = push_str8_copy(arena, expr_string); - } - } -} - -E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(watches) -{ - U64 id = 0; - RD_CfgArray *cfgs = (RD_CfgArray *)user_data; - if(1 <= num && num <= cfgs->count) - { - U64 idx = (num-1); - id = cfgs->v[idx]->id; - } - else if(num == cfgs->count+1) - { - id = max_U64; - } - return id; -} - -E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(watches) -{ - U64 num = 0; - RD_CfgArray *cfgs = (RD_CfgArray *)user_data; - if(id != 0 && id != max_U64) - { - for EachIndex(idx, cfgs->count) - { - if(cfgs->v[idx]->id == id) - { - num = idx+1; - break; - } - } - } - else if(id == max_U64) - { - num = cfgs->count + 1; - } - return num; -} - -//////////////////////////////// -//~ rjf: Locals Eval Hooks - -E_LOOKUP_INFO_FUNCTION_DEF(locals) -{ - E_LookupInfo result = {0}; - Temp scratch = scratch_begin(&arena, 1); - { - E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_ir_state->ctx->locals_map); - e_string2num_map_node_array_sort__in_place(&nodes); - String8List exprs_filtered = {0}; - for EachIndex(idx, nodes.count) - { - String8 local_expr_string = nodes.v[idx]->string; - FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, local_expr_string); - if(matches.count == matches.needle_part_count) - { - str8_list_push(scratch.arena, &exprs_filtered, local_expr_string); - } - } - String8Array *accel = push_array(arena, String8Array, 1); - *accel = str8_array_from_list(arena, &exprs_filtered); - result.user_data = accel; - result.idxed_expr_count = accel->count; - } - scratch_end(scratch); - return result; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(locals) -{ - String8Array *accel = (String8Array *)user_data; - Rng1U64 legal_idx_range = r1u64(0, accel->count); - Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); - U64 read_range_count = dim_1u64(read_range); - for(U64 idx = 0; idx < read_range_count; idx += 1) - { - String8 expr_string = accel->v[read_range.min + idx]; - exprs[idx] = e_parse_expr_from_text(arena, expr_string).exprs.last; - exprs_strings[idx] = push_str8_copy(arena, expr_string); - } -} - -//////////////////////////////// -//~ rjf: Registers Eval Hooks - -E_LOOKUP_INFO_FUNCTION_DEF(registers) -{ - Temp scratch = scratch_begin(&arena, 1); - CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->thread); - Arch arch = thread->arch; - U64 reg_count = regs_reg_code_count_from_arch(arch); - U64 alias_count = regs_alias_code_count_from_arch(arch); - String8 *reg_strings = regs_reg_code_string_table_from_arch(arch); - String8 *alias_strings = regs_alias_code_string_table_from_arch(arch); - String8List exprs_list = {0}; - for(U64 idx = 1; idx < reg_count; idx += 1) - { - FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, reg_strings[idx]); - if(matches.count == matches.needle_part_count) - { - str8_list_push(scratch.arena, &exprs_list, reg_strings[idx]); - } - } - for(U64 idx = 1; idx < alias_count; idx += 1) - { - FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, alias_strings[idx]); - if(matches.count == matches.needle_part_count) - { - str8_list_push(scratch.arena, &exprs_list, alias_strings[idx]); - } - } - String8Array *accel = push_array(arena, String8Array, 1); - *accel = str8_array_from_list(arena, &exprs_list); - E_LookupInfo info = {accel, 0, accel->count}; - scratch_end(scratch); - return info; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(registers) -{ - String8Array *accel = (String8Array *)user_data; - Rng1U64 legal_idx_range = r1u64(0, accel->count); - Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); - U64 read_range_count = dim_1u64(read_range); - for(U64 idx = 0; idx < read_range_count; idx += 1) - { - String8 register_name = accel->v[read_range.min + idx]; - String8 register_expr = push_str8f(arena, "reg:%S", register_name); - exprs_strings[idx] = register_name; - exprs[idx] = e_parse_expr_from_text(arena, register_expr).exprs.last; - } -} - -//////////////////////////////// -//~ rjf: Schema'd Set Eval Hooks - -typedef struct RD_SchemaLookupAccel RD_SchemaLookupAccel; -struct RD_SchemaLookupAccel -{ - RD_Cfg *cfg; - CTRL_Entity *entity; - MD_Node *schema; - MD_Node **children; - U64 children_count; -}; - -E_LOOKUP_INFO_FUNCTION_DEF(schema) -{ - E_LookupInfo result = {0}; - { - Temp scratch = scratch_begin(&arena, 1); - - // rjf: unpack - E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs->root); - String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); - E_Interpretation interpret = e_interpret(bytecode); - E_TypeKey type_key = lhs->type_key; - E_Type *type = e_type_from_key__cached(type_key); - MD_Node *schema = rd_schema_from_name(type->name); - - // rjf: gather expansion children - typedef struct ExpandChildNode ExpandChildNode; - struct ExpandChildNode - { - ExpandChildNode *next; - MD_Node *n; - }; - ExpandChildNode *first_child_node = 0; - ExpandChildNode *last_child_node = 0; - U64 child_count = 0; - for MD_EachNode(child, schema->first) - { - if(!md_node_has_tag(child, str8_lit("no_expand"), 0)) - { - FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, child->string); - if(matches.count == matches.needle_part_count) - { - ExpandChildNode *n = push_array(scratch.arena, ExpandChildNode, 1); - n->n = child; - SLLQueuePush(first_child_node, last_child_node, n); - child_count += 1; - } - } - } - - // rjf: flatten expansion member list - MD_Node **children = push_array(arena, MD_Node *, child_count); - { - U64 idx = 0; - for(ExpandChildNode *n = first_child_node; n != 0; n = n->next, idx += 1) - { - children[idx] = n->n; - } - } - - // rjf: build accelerator for lookups - RD_SchemaLookupAccel *accel = push_array(arena, RD_SchemaLookupAccel, 1); - accel->cfg = rd_cfg_from_eval_space(interpret.space); - accel->entity = rd_ctrl_entity_from_eval_space(interpret.space); - accel->schema = schema; - accel->children = children; - accel->children_count = child_count; - - // rjf: fill result - result.user_data = accel; - result.named_expr_count = child_count; - - scratch_end(scratch); - } - return result; -} - -E_LOOKUP_ACCESS_FUNCTION_DEF(schema) -{ - RD_SchemaLookupAccel *accel = (RD_SchemaLookupAccel *)user_data; - E_IRTreeAndType irtree = {&e_irnode_nil}; - if(kind == E_ExprKind_MemberAccess) - { - MD_Node *child_schema = &md_nil_node; - for MD_EachNode(child, accel->schema->first) - { - if(str8_match(child->string, rhs->string, 0)) - { - child_schema = child; - break; - } - } - if(child_schema != &md_nil_node) - { - RD_Cfg *cfg = accel->cfg; - CTRL_Entity *entity = accel->entity; - RD_Cfg *child = rd_cfg_child_from_string(cfg, child_schema->string); - E_TypeKey child_type_key = zero_struct; - if(0){} - - //- rjf: ctrl entity members - else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("label"), 0)) - { - child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, E_TypeFlag_IsCodeText); - } - else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("exe"), 0)) - { - child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, E_TypeFlag_IsPathText); - } - else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("dbg"), 0)) - { - CTRL_Entity *dbg = ctrl_entity_child_from_kind(entity, CTRL_EntityKind_DebugInfoPath); - child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), dbg->string.size, E_TypeFlag_IsPathText); - } - - //- rjf: cfg members - else if(str8_match(child_schema->first->string, str8_lit("code_string"), 0)) - { - child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsCodeText); - } - else if(str8_match(child_schema->first->string, str8_lit("path"), 0)) - { - child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPathText); - } - else if(str8_match(child_schema->first->string, str8_lit("path_pt"), 0)) - { - Temp scratch = scratch_begin(&arena, 1); - String8 string = push_str8f(scratch.arena, "%S%s%S%s%S", child->first->string, child->first->string.size ? ":" : "", child->first->first->string, child->first->first->first->string.size ? ":" : "", child->first->first->first->string); - child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), string.size, E_TypeFlag_IsPathText); - scratch_end(scratch); - } - else if(str8_match(child_schema->first->string, str8_lit("string"), 0)) - { - child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPlainText); - } - - //- rjf: catchall cases - else if(str8_match(child_schema->first->string, str8_lit("u64"), 0)) - { - child_type_key = e_type_key_basic(E_TypeKind_U64); - } - else if(str8_match(child_schema->first->string, str8_lit("bool"), 0)) - { - child_type_key = e_type_key_basic(E_TypeKind_Bool); - } - else if(str8_match(child_schema->first->string, str8_lit("vaddr_range"), 0)) - { - Temp scratch = scratch_begin(&arena, 1); - E_MemberList vaddr_range_members_list = {0}; - e_member_list_push_new(scratch.arena, &vaddr_range_members_list, .type_key = e_type_key_basic(E_TypeKind_U64), .name = str8_lit("min"), .off = 0); - e_member_list_push_new(scratch.arena, &vaddr_range_members_list, .type_key = e_type_key_basic(E_TypeKind_U64), .name = str8_lit("max"), .off = 8); - E_MemberArray vaddr_range_members = e_member_array_from_list(scratch.arena, &vaddr_range_members_list); - child_type_key = e_type_key_cons(.kind = E_TypeKind_Struct, .name = str8_lit("vaddr_range"), .count = vaddr_range_members.count, .members = vaddr_range_members.v); - scratch_end(scratch); - } - else if(str8_match(child_schema->first->string, str8_lit("query"), 0)) - { - child_type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = child_schema->string); - } - - //- rjf: evaluate - E_Space child_eval_space = zero_struct; - if(cfg != &rd_nil_cfg) - { - child_eval_space = e_space_make(RD_EvalSpaceKind_MetaCfg); - child_eval_space.u64s[0] = cfg->id; - child_eval_space.u64s[1] = e_id_from_string(child_schema->string); - } - else - { - child_eval_space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); - child_eval_space.u64s[2] = e_id_from_string(child_schema->string); - } - irtree.root = e_irtree_set_space(arena, child_eval_space, e_push_irnode(arena, RDI_EvalOp_ConstU64)); - irtree.type_key = child_type_key; - irtree.mode = E_Mode_Offset; - } - } - E_LookupAccess access = {irtree}; - return access; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(schema) -{ - E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); - RD_SchemaLookupAccel *accel = (RD_SchemaLookupAccel *)user_data; - U64 out_idx = 0; - for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) - { - if(0 <= idx && idx < accel->children_count) - { - MD_Node *child_schema = accel->children[idx]; - exprs[out_idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, child_schema->string); - } - } -} - -//////////////////////////////// -//~ rjf: Config Collection Eval Hooks - -typedef struct RD_CfgCollectionLookupAccel RD_CfgCollectionLookupAccel; -struct RD_CfgCollectionLookupAccel -{ - String8Array cmds; - RD_CfgArray cfgs; - Rng1U64 cmds_idx_range; - Rng1U64 cfgs_idx_range; -}; - -E_LOOKUP_INFO_FUNCTION_DEF(cfgs) -{ - E_LookupInfo result = {0}; - Temp scratch = scratch_begin(&arena, 1); - { - //- rjf: determine which cfg we'll use to scope the lookups - E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs->root); - String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); - E_Interpretation lhs_interp = e_interpret(lhs_bytecode); - RD_Cfg *scoping_cfg = rd_cfg_from_eval_space(lhs_interp.space); - - //- rjf: determine which kind of child we'll be gathering - E_TypeKey lhs_type_key = lhs->type_key; - E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); - String8 cfg_name = rd_singular_from_code_name_plural(lhs_type->name); - - //- rjf: gather cfgs - RD_CfgList cfgs_list = {0}; - if(scoping_cfg == &rd_nil_cfg) - { - cfgs_list = rd_cfg_top_level_list_from_string(scratch.arena, cfg_name); - } - else - { - cfgs_list = rd_cfg_child_list_from_string(scratch.arena, scoping_cfg, cfg_name); - } - - //- rjf: filter cfgs - RD_CfgList cfgs_list__filtered = cfgs_list; - if(filter.size != 0) - { - MemoryZeroStruct(&cfgs_list__filtered); - for(RD_CfgNode *n = cfgs_list.first; n != 0; n = n->next) - { - DR_FStrList fstrs = rd_title_fstrs_from_cfg(scratch.arena, n->v); - String8 string = dr_string_from_fstrs(scratch.arena, &fstrs); - FuzzyMatchRangeList fuzzy_matches = fuzzy_match_find(scratch.arena, filter, string); - if(fuzzy_matches.count == fuzzy_matches.needle_part_count) - { - rd_cfg_list_push(scratch.arena, &cfgs_list__filtered, n->v); - } - } - } - - //- rjf: gather commands - String8List cmds_list = {0}; - if(filter.size == 0) - { - MD_Node *schema = rd_schema_from_name(cfg_name); - MD_Node *collection_cmds_root = md_tag_from_string(schema, str8_lit("collection_commands"), 0); - for MD_EachNode(cmd, collection_cmds_root->first) - { - str8_list_push(arena, &cmds_list, cmd->string); - } - } - - //- rjf: package & fill - RD_CfgCollectionLookupAccel *accel = push_array(arena, RD_CfgCollectionLookupAccel, 1); - accel->cfgs = rd_cfg_array_from_list(arena, &cfgs_list__filtered); - accel->cmds = str8_array_from_list(arena, &cmds_list); - accel->cmds_idx_range = r1u64(0, accel->cmds.count); - accel->cfgs_idx_range = r1u64(accel->cmds_idx_range.max, accel->cmds_idx_range.max + accel->cfgs.count); - result.user_data = accel; - result.idxed_expr_count = accel->cfgs.count + accel->cmds.count; - } - scratch_end(scratch); - return result; -} - -E_LOOKUP_ACCESS_FUNCTION_DEF(cfgs) -{ - Temp scratch = scratch_begin(&arena, 1); - E_LookupAccess result = {{&e_irnode_nil}}; - RD_Cfg *cfg = &rd_nil_cfg; - if(kind == E_ExprKind_MemberAccess) - { - String8 rhs_name = rhs->string; - RD_CfgID id = 0; - if(str8_match(str8_prefix(rhs_name, 1), str8_lit("$"), 0) && - try_u64_from_str8_c_rules(str8_skip(rhs_name, 1), &id)) - { - cfg = rd_cfg_from_id(id); - } - } - else if(kind == E_ExprKind_ArrayIndex) - { - E_IRTreeAndType rhs_irtree = e_irtree_and_type_from_expr(scratch.arena, rhs); - E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); - String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); - E_Interpretation rhs_interp = e_interpret(rhs_bytecode); - E_Value rhs_value = rhs_interp.value; - U64 rhs_idx = rhs_value.u64; - RD_CfgCollectionLookupAccel *accel = (RD_CfgCollectionLookupAccel *)user_data; - if(0 <= rhs_idx && rhs_idx < accel->cfgs.count) - { - cfg = accel->cfgs.v[rhs_idx]; - } - } - if(cfg != &rd_nil_cfg) - { - E_Space cfg_space = rd_eval_space_from_cfg(cfg); - String8 cfg_name = cfg->string; - E_TypeKey cfg_type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, cfg_name); - result.irtree_and_type.root = e_irtree_set_space(arena, cfg_space, e_irtree_const_u(arena, 0)); - result.irtree_and_type.type_key = cfg_type_key; - result.irtree_and_type.mode = E_Mode_Offset; - } - scratch_end(scratch); - return result; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(cfgs) -{ - RD_CfgCollectionLookupAccel *accel = (RD_CfgCollectionLookupAccel *)user_data; - Rng1U64 cmds_idx_range = accel->cmds_idx_range; - Rng1U64 cfgs_idx_range = accel->cfgs_idx_range; - U64 dst_idx = 0; - E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); - - // rjf: fill commands - { - Rng1U64 read_range = intersect_1u64(cmds_idx_range, idx_range); - U64 read_count = dim_1u64(read_range); - E_Expr *commands = e_parse_expr_from_text(arena, str8_lit("query:commands")).exprs.last; - E_IRTreeAndType commands_irtree = e_irtree_and_type_from_expr(arena, commands); - for(U64 idx = 0; idx < read_count; idx += 1, dst_idx += 1) - { - String8 cmd_name = accel->cmds.v[idx + read_range.min - cmds_idx_range.min]; - exprs[dst_idx] = e_expr_irext_member_access(arena, commands, &commands_irtree, cmd_name); - } - } - - // rjf: fill cfgs - { - Rng1U64 read_range = intersect_1u64(cfgs_idx_range, idx_range); - U64 read_count = dim_1u64(read_range); - for(U64 idx = 0; idx < read_count; idx += 1, dst_idx += 1) - { - RD_Cfg *cfg = accel->cfgs.v[idx + read_range.min - cfgs_idx_range.min]; - exprs[dst_idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, push_str8f(arena, "$%I64d", cfg->id)); - } - } -} - -E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(cfgs) -{ - U64 id = 0; - RD_CfgCollectionLookupAccel *accel = (RD_CfgCollectionLookupAccel *)user_data; - if(num != 0) - { - U64 idx = num-1; - if(contains_1u64(accel->cfgs_idx_range, idx)) - { - RD_Cfg *cfg = accel->cfgs.v[idx - accel->cfgs_idx_range.min]; - id = cfg->id; - } - else if(contains_1u64(accel->cmds_idx_range, idx)) - { - id = num; - id |= (1ull<<63); - } - } - return id; -} - -E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(cfgs) -{ - U64 num = 0; - RD_CfgCollectionLookupAccel *accel = (RD_CfgCollectionLookupAccel *)user_data; - if(id != 0) - { - if(id & (1ull<<63)) - { - num = id; - num &= ~(1ull<<63); - } - else for EachIndex(idx, accel->cfgs.count) - { - if(accel->cfgs.v[idx]->id == id) - { - num = idx + accel->cfgs_idx_range.min + 1; - break; - } - } - } - return num; -} - -//////////////////////////////// -//~ rjf: Call Stack Eval Hooks - -typedef struct RD_CallStackLookupAccel RD_CallStackLookupAccel; -struct RD_CallStackLookupAccel -{ - Arch arch; - CTRL_Handle process; - CTRL_CallStack call_stack; -}; - -E_LOOKUP_INFO_FUNCTION_DEF(call_stack) -{ - E_LookupInfo result = {0}; - Temp scratch = scratch_begin(&arena, 1); - { - RD_CallStackLookupAccel *accel = push_array(arena, RD_CallStackLookupAccel, 1); - E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs->root); - String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); - E_Interpretation interp = e_interpret(bytecode); - CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(interp.space); - if(entity->kind == CTRL_EntityKind_Thread) - { - CTRL_Entity *process = ctrl_process_from_entity(entity); - CTRL_Unwind base_unwind = d_query_cached_unwind_from_thread(entity); - accel->arch = entity->arch; - accel->process = process->handle; - accel->call_stack = ctrl_call_stack_from_unwind(arena, rd_state->frame_di_scope, process, &base_unwind); - result.idxed_expr_count = accel->call_stack.count; - } - result.user_data = accel; - } - scratch_end(scratch); - return result; -} - -E_LOOKUP_ACCESS_FUNCTION_DEF(call_stack) -{ - E_LookupAccess result = {{&e_irnode_nil}}; - if(kind == E_ExprKind_ArrayIndex) - { - Temp scratch = scratch_begin(&arena, 1); - E_IRTreeAndType rhs_irtree = e_irtree_and_type_from_expr(scratch.arena, rhs); - E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); - String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); - E_Interpretation rhs_interp = e_interpret(rhs_bytecode); - E_Value rhs_value = rhs_interp.value; - RD_CallStackLookupAccel *accel = (RD_CallStackLookupAccel *)user_data; - CTRL_CallStack *call_stack = &accel->call_stack; - if(0 <= rhs_value.u64 && rhs_value.u64 < call_stack->count) - { - CTRL_Entity *process = ctrl_entity_from_handle(d_state->ctrl_entity_store, accel->process); - CTRL_CallStackFrame *f = &call_stack->frames[rhs_value.u64]; - result.irtree_and_type.root = e_irtree_set_space(arena, rd_eval_space_from_ctrl_entity(process, RD_EvalSpaceKind_CtrlEntity), e_irtree_const_u(arena, regs_rip_from_arch_block(accel->arch, f->regs))); - result.irtree_and_type.type_key = e_type_key_cons(.arch = process->arch, .kind = E_TypeKind_Ptr, .direct_key = e_type_key_basic(E_TypeKind_Function), .count = 1, .depth = f->inline_depth); - result.irtree_and_type.mode = E_Mode_Value; - } - scratch_end(scratch); - } - return result; -} - -//////////////////////////////// -//~ rjf: Target / Environment Eval Hooks - -E_LOOKUP_INFO_FUNCTION_DEF(environment) -{ - E_LookupInfo result = {0}; - Temp scratch = scratch_begin(&arena, 1); - { - E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs->root); - String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); - E_Interpretation interpret = e_interpret(bytecode); - RD_Cfg *target = rd_cfg_from_eval_space(interpret.space); - RD_CfgList env_strings = {0}; - for(RD_Cfg *child = target->first; child != &rd_nil_cfg; child = child->next) - { - if(str8_match(child->string, str8_lit("environment"), 0)) - { - rd_cfg_list_push(scratch.arena, &env_strings, child); - } - } - RD_CfgArray *accel = push_array(arena, RD_CfgArray, 1); - *accel = rd_cfg_array_from_list(arena, &env_strings); - result.user_data = accel; - result.idxed_expr_count = accel->count + 1; - } - scratch_end(scratch); - return result; -} - -E_LOOKUP_ACCESS_FUNCTION_DEF(environment) -{ - E_LookupAccess result = {{&e_irnode_nil}}; - if(kind == E_ExprKind_ArrayIndex) - { - Temp scratch = scratch_begin(&arena, 1); - RD_CfgArray *cfgs = (RD_CfgArray *)user_data; - E_IRTreeAndType rhs_irtree = e_irtree_and_type_from_expr(scratch.arena, rhs); - E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); - String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); - E_Interpretation rhs_interp = e_interpret(rhs_bytecode); - E_Value rhs_value = rhs_interp.value; - if(0 <= rhs_value.u64 && rhs_value.u64 < cfgs->count) - { - RD_Cfg *cfg = cfgs->v[rhs_value.u64]; - result.irtree_and_type.root = e_irtree_set_space(arena, rd_eval_space_from_cfg(cfg), e_irtree_const_u(arena, 0)); - result.irtree_and_type.type_key = e_type_key_cons_ptr(arch_from_context(), e_type_key_basic(E_TypeKind_U8), 1, E_TypeFlag_IsCodeText); - result.irtree_and_type.mode = E_Mode_Offset; - } - scratch_end(scratch); - } - return result; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(environment) -{ - RD_CfgArray *cfgs = (RD_CfgArray *)user_data; - E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); - Rng1U64 legal_idx_range = r1u64(0, cfgs->count); - Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); - U64 read_range_count = dim_1u64(read_range); - for(U64 idx = 0; idx < read_range_count; idx += 1) - { - U64 cfg_idx = read_range.min + idx; - if(cfg_idx < cfgs->count) - { - exprs[idx] = e_expr_irext_array_index(arena, lhs, &lhs_irtree, cfg_idx); - } - } -} - -E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(environment) -{ - U64 id = 0; - RD_CfgArray *cfgs = (RD_CfgArray *)user_data; - if(1 <= num && num <= cfgs->count) - { - U64 idx = (num-1); - id = cfgs->v[idx]->id; - } - else if(num == cfgs->count+1) - { - id = max_U64; - } - return id; -} - -E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(environment) -{ - U64 num = 0; - RD_CfgArray *cfgs = (RD_CfgArray *)user_data; - if(id != 0 && id != max_U64) - { - for EachIndex(idx, cfgs->count) - { - if(cfgs->v[idx]->id == id) - { - num = idx+1; - break; - } - } - } - else if(id == max_U64) - { - num = cfgs->count + 1; - } - return num; -} - -//////////////////////////////// -//~ rjf: Unattached System Process List Eval Hooks - -typedef struct RD_UnattachedProcessesAccel RD_UnattachedProcessesAccel; -struct RD_UnattachedProcessesAccel -{ - DMN_ProcessInfo *infos; - CTRL_Entity **machines; - U64 infos_count; -}; - -E_LOOKUP_INFO_FUNCTION_DEF(unattached_processes) -{ - E_LookupInfo info = {0}; - { - Temp scratch = scratch_begin(&arena, 1); - - //- rjf: evaluate lhs machine, if we have one - E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs->root); - String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); - E_Interpretation lhs_interp = e_interpret(lhs_bytecode); - CTRL_Entity *lhs_entity = rd_ctrl_entity_from_eval_space(lhs_interp.space); - - //- rjf: gather all machines we're searching through - CTRL_EntityList machines = {0}; - if(lhs_entity->kind == CTRL_EntityKind_Machine) - { - ctrl_entity_list_push(scratch.arena, &machines, lhs_entity); - } - else - { - machines = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Machine); - } - - //- rjf: gather system processes from this machine - typedef struct Node Node; - struct Node - { - Node *next; - CTRL_Entity *machine; - DMN_ProcessInfo info; - }; - Node *first = 0; - Node *last = 0; - U64 count = 0; - for(CTRL_EntityNode *n = machines.first; n != 0; n = n->next) - { - CTRL_Entity *machine = n->v; - DMN_ProcessIter iter = {0}; - dmn_process_iter_begin(&iter); - for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &iter, &info);) - { - B32 passes_filter = 1; - if(filter.size != 0) - { - passes_filter = 0; - FuzzyMatchRangeList name_matches = fuzzy_match_find(scratch.arena, filter, info.name); - FuzzyMatchRangeList pid_matches = fuzzy_match_find(scratch.arena, filter, push_str8f(scratch.arena, "%I64u", info.pid)); - if(name_matches.count == name_matches.needle_part_count || pid_matches.count == pid_matches.needle_part_count) - { - passes_filter = 1; - } - } - if(passes_filter) - { - Node *node = push_array(scratch.arena, Node, 1); - SLLQueuePush(first, last, node); - node->machine = machine; - node->info = info; - count += 1; - } - } - dmn_process_iter_end(&iter); - } - - //- rjf: list -> array - U64 infos_count = count; - DMN_ProcessInfo *infos = push_array(arena, DMN_ProcessInfo, infos_count); - CTRL_Entity **infos_machines = push_array(arena, CTRL_Entity *, infos_count); - { - U64 idx = 0; - for(Node *n = first; n != 0; n = n->next, idx += 1) - { - infos[idx] = n->info; - infos[idx].name = push_str8_copy(arena, infos[idx].name); - infos_machines[idx] = n->machine; - } - } - - //- rjf: build accelerator - RD_UnattachedProcessesAccel *accel = push_array(arena, RD_UnattachedProcessesAccel, 1); - accel->infos = infos; - accel->infos_count = infos_count; - accel->machines = infos_machines; - info.user_data = accel; - info.idxed_expr_count = infos_count; - scratch_end(scratch); - } - return info; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(unattached_processes) -{ - RD_UnattachedProcessesAccel *accel = (RD_UnattachedProcessesAccel *)user_data; - U64 out_idx = 0; - E_TypeKey unattached_process_type = e_type_key_cons(.kind = E_TypeKind_U128, .name = str8_lit("unattached_process")); - for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) - { - E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); - expr->type_key = unattached_process_type; - expr->value.u128.u64[0] = accel->infos[idx].pid; - expr->value.u128.u64[1] = e_id_from_string(accel->infos[idx].name); - expr->space = rd_eval_space_from_ctrl_entity(accel->machines[idx], RD_EvalSpaceKind_MetaUnattachedProcess); - exprs[out_idx] = expr; - } -} - -//////////////////////////////// -//~ rjf: Control Entity Eval Hooks - -E_LOOKUP_INFO_FUNCTION_DEF(ctrl_entities) -{ - E_LookupInfo result = {0}; - Temp scratch = scratch_begin(&arena, 1); - { - //- rjf: determine which entity we're looking under - E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs->root); - String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); - E_Interpretation lhs_interp = e_interpret(lhs_bytecode); - CTRL_Entity *scoping_entity = &ctrl_entity_nil; - if(lhs_interp.space.kind == RD_EvalSpaceKind_MetaCtrlEntity) - { - scoping_entity = rd_ctrl_entity_from_eval_space(lhs_interp.space); - } - - //- rjf: determine which type of child we're gathering - E_TypeKey lhs_type_key = lhs->type_key; - E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); - String8 name = rd_singular_from_code_name_plural(lhs_type->name); - CTRL_EntityKind entity_kind = CTRL_EntityKind_Null; - for EachNonZeroEnumVal(CTRL_EntityKind, k) - { - if(str8_match(name, ctrl_entity_kind_code_name_table[k], 0)) - { - entity_kind = k; - break; - } - } - - //- rjf: gather list of all entities which fit the bill - CTRL_EntityList list = {0}; - if(scoping_entity == &ctrl_entity_nil) - { - list = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, entity_kind); - } - else - { - for(CTRL_Entity *child = scoping_entity->first; child != &ctrl_entity_nil; child = child->next) - { - if(child->kind == entity_kind) - { - ctrl_entity_list_push(scratch.arena, &list, child); - } - } - } - - //- rjf: filter the list - CTRL_EntityList list__filtered = list; - if(filter.size != 0) - { - MemoryZeroStruct(&list__filtered); - for(CTRL_EntityNode *n = list.first; n != 0; n = n->next) - { - CTRL_Entity *entity = n->v; - DR_FStrList fstrs = rd_title_fstrs_from_ctrl_entity(scratch.arena, entity, 1); - String8 title_string = dr_string_from_fstrs(scratch.arena, &fstrs); - FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, title_string); - if(matches.count == matches.needle_part_count) - { - ctrl_entity_list_push(scratch.arena, &list__filtered, entity); - } - } - } - - //- rjf: list -> array & fill - CTRL_EntityArray *array = push_array(arena, CTRL_EntityArray, 1); - *array = ctrl_entity_array_from_list(arena, &list__filtered); - result.user_data = array; - result.idxed_expr_count = array->count; - } - scratch_end(scratch); - return result; -} - -E_LOOKUP_ACCESS_FUNCTION_DEF(ctrl_entities) -{ - Temp scratch = scratch_begin(&arena, 1); - E_LookupAccess result = {{&e_irnode_nil}}; - CTRL_Entity *entity = &ctrl_entity_nil; - if(kind == E_ExprKind_MemberAccess) - { - String8 rhs_name = rhs->string; - CTRL_Handle handle = ctrl_handle_from_string(rhs_name); - entity = ctrl_entity_from_handle(d_state->ctrl_entity_store, handle); - } - else if(kind == E_ExprKind_ArrayIndex) - { - E_IRTreeAndType rhs_irtree = e_irtree_and_type_from_expr(scratch.arena, rhs); - E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); - String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); - E_Interpretation rhs_interp = e_interpret(rhs_bytecode); - E_Value rhs_value = rhs_interp.value; - U64 rhs_idx = rhs_value.u64; - CTRL_EntityArray *entities = (CTRL_EntityArray *)user_data; - if(0 <= rhs_idx && rhs_idx < entities->count) - { - entity = entities->v[rhs_idx]; - } - } - if(entity != &ctrl_entity_nil) - { - E_Space space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); - String8 name = ctrl_entity_kind_code_name_table[entity->kind]; - E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, name); - result.irtree_and_type.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); - result.irtree_and_type.type_key = type_key; - result.irtree_and_type.mode = E_Mode_Offset; - } - scratch_end(scratch); - return result; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(ctrl_entities) -{ - CTRL_EntityArray *entities = (CTRL_EntityArray *)user_data; - E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); - Rng1U64 legal_range = r1u64(0, entities->count); - Rng1U64 read_range = intersect_1u64(legal_range, idx_range); - U64 read_count = dim_1u64(read_range); - for(U64 out_idx = 0; out_idx < read_count; out_idx += 1) - { - CTRL_Entity *entity = entities->v[out_idx + read_range.min]; - exprs[out_idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, ctrl_string_from_handle(arena, entity->handle)); - } -} - -//////////////////////////////// -//~ rjf: Debug Info Tables Eval Hooks - -typedef struct RD_DebugInfoTableLookupAccel RD_DebugInfoTableLookupAccel; -struct RD_DebugInfoTableLookupAccel -{ - RDI_SectionKind section; - U64 rdis_count; - RDI_Parsed **rdis; - DI_SearchItemArray items; -}; - -E_LOOKUP_INFO_FUNCTION_DEF(debug_info_table) -{ - Temp scratch = scratch_begin(&arena, 1); - - // rjf: determine which debug info section we're dealing with - RDI_SectionKind section = RDI_SectionKind_NULL; - { - E_TypeKey lhs_type_key = lhs->type_key; - E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); - if(0){} - else if(str8_match(lhs_type->name, str8_lit("procedures"), 0)) {section = RDI_SectionKind_Procedures;} - else if(str8_match(lhs_type->name, str8_lit("globals"), 0)) {section = RDI_SectionKind_GlobalVariables;} - else if(str8_match(lhs_type->name, str8_lit("thread_locals"), 0)) {section = RDI_SectionKind_ThreadVariables;} - else if(str8_match(lhs_type->name, str8_lit("types"), 0)) {section = RDI_SectionKind_UDTs;} - } - - // rjf: gather debug info table items - RD_DebugInfoTableLookupAccel *accel = push_array(arena, RD_DebugInfoTableLookupAccel, 1); - if(section != RDI_SectionKind_NULL) - { - U64 endt_us = rd_state->frame_eval_memread_endt_us; - - //- rjf: unpack context - DI_KeyList dbgi_keys_list = d_push_active_dbgi_key_list(scratch.arena); - DI_KeyArray dbgi_keys = di_key_array_from_list(scratch.arena, &dbgi_keys_list); - U64 rdis_count = dbgi_keys.count; - RDI_Parsed **rdis = push_array(arena, RDI_Parsed *, rdis_count); - for(U64 idx = 0; idx < rdis_count; idx += 1) - { - rdis[idx] = di_rdi_from_key(rd_state->frame_di_scope, &dbgi_keys.v[idx], endt_us); - } - - //- rjf: query all filtered items from dbgi searching system - U128 fuzzy_search_key = {d_hash_from_string(str8_struct(&rd_regs()->view)), (U64)section}; - B32 items_stale = 0; - DI_SearchParams params = {section, dbgi_keys}; - accel->section = section; - accel->rdis_count = rdis_count; - accel->rdis = rdis; - accel->items = di_search_items_from_key_params_query(rd_state->frame_di_scope, fuzzy_search_key, ¶ms, filter, endt_us, &items_stale); - if(items_stale) - { - rd_request_frame(); - } - } - E_LookupInfo info = {accel, 0, accel->items.count}; - scratch_end(scratch); - return info; -} - -E_LOOKUP_RANGE_FUNCTION_DEF(debug_info_table) -{ - RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; - U64 needed_row_count = dim_1u64(idx_range); - for EachIndex(idx, needed_row_count) - { - // rjf: unpack row - DI_SearchItem *item = &accel->items.v[idx_range.min + idx]; - - // rjf: skip bad elements - if(item->dbgi_idx >= accel->rdis_count) - { - continue; - } - - // rjf: unpack row info - RDI_Parsed *rdi = accel->rdis[item->dbgi_idx]; - E_Module *module = &e_parse_state->ctx->modules[item->dbgi_idx]; - - // rjf: build expr - E_Expr *item_expr = &e_expr_nil; - { - U64 element_idx = item->idx; - switch(accel->section) - { - default:{}break; - case RDI_SectionKind_Procedures: - { - Temp scratch = scratch_begin(&arena, 1); - 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_ConstU64, e_value_u64(module->vaddr_range.min + 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_state->ctx->modules)); - String8 symbol_name = {0}; - symbol_name.str = rdi_string_from_idx(module->rdi, procedure->name_string_idx, &symbol_name.size); - String8List strings = {0}; - e_type_lhs_string_from_key(scratch.arena, type_key, &strings, 0, 0); - str8_list_push(scratch.arena, &strings, symbol_name); - e_type_rhs_string_from_key(scratch.arena, type_key, &strings, 0); - item_expr = e_push_expr(arena, E_ExprKind_LeafBytecode, 0); - item_expr->mode = E_Mode_Value; - item_expr->space = module->space; - item_expr->type_key = type_key; - item_expr->bytecode = bytecode; - item_expr->string = str8_list_join(arena, &strings, 0); - scratch_end(scratch); - }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_ConstU64, e_value_u64(module->vaddr_range.min + 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_state->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, e_value_u64(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_state->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_state->ctx->modules)); - item_expr = e_push_expr(arena, E_ExprKind_TypeIdent, 0); - item_expr->type_key = type_key; - }break; - } - } - - // rjf: fill - exprs[idx] = item_expr; - } -} - -E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(debug_info_table) -{ - RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; - U64 id = 0; - if(0 < num && num <= accel->items.count) - { - id = accel->items.v[num-1].idx+1; - } - return id; -} - -E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(debug_info_table) -{ - RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; - U64 num = di_search_item_num_from_array_element_idx__linear_search(&accel->items, id-1); - return num; -} - //////////////////////////////// //~ rjf: Config ID Type Functions @@ -3901,7 +2632,7 @@ rd_view_ui(Rng2F32 rect) { ev_key_set_expansion(eval_view, ev_key_root(), ev_key_make(ev_hash_from_key(ev_key_root()), 1), 1); } - block_tree = ev_block_tree_from_exprs(scratch.arena, eval_view, filter, eval.exprs); + block_tree = ev_block_tree_from_expr(scratch.arena, eval_view, filter, eval.expr); block_ranges = ev_block_range_list_from_tree(scratch.arena, &block_tree); if(implicit_root && block_ranges.first != 0) { @@ -4098,10 +2829,10 @@ rd_view_ui(Rng2F32 rect) } // rjf: use row to complete query - if(row->expr != &e_expr_nil) + if(row->eval.expr != &e_expr_nil) { taken = 1; - E_Eval eval = e_eval_from_expr(scratch.arena, row->expr); + E_Eval eval = row->eval; switch(eval.space.kind) { default: @@ -4500,13 +3231,13 @@ rd_view_ui(Rng2F32 rect) if(cfg != &rd_nil_cfg) { rd_cfg_list_push(scratch.arena, &cfgs_to_remove, cfg); - U64 deleted_num = row->block->lookup_rule->num_from_id(row->key.child_id, row->block->lookup_rule_user_data); + U64 deleted_num = ev_block_num_from_id(row->block, row->key.child_id); if(deleted_num != 0) { EV_Key parent_key = row->block->parent->key; EV_Key key = row->block->key; - U64 fallback_id_prev = row->block->lookup_rule->id_from_num(deleted_num-1, row->block->lookup_rule_user_data); - U64 fallback_id_next = row->block->lookup_rule->id_from_num(deleted_num+1, row->block->lookup_rule_user_data); + U64 fallback_id_prev = ev_block_id_from_num(row->block, deleted_num-1); + U64 fallback_id_next = ev_block_id_from_num(row->block, deleted_num+1); if(fallback_id_next != 0) { parent_key = row->block->key; @@ -4703,7 +3434,7 @@ rd_view_ui(Rng2F32 rect) // rjf: determine collection info for the block String8 group_cfg_name = {0}; { - E_IRTreeAndType block_irtree = e_irtree_and_type_from_expr(scratch.arena, selection_block->expr); + E_IRTreeAndType block_irtree = selection_block->eval.irtree; E_TypeKey block_type_key = block_irtree.type_key; E_TypeKind block_type_kind = e_type_kind_from_key(block_type_key); if(block_type_kind == E_TypeKind_Set) @@ -5083,17 +3814,17 @@ rd_view_ui(Rng2F32 rect) ProfBegin("determine if row's data is fresh and/or bad"); B32 row_is_fresh = 0; B32 row_is_bad = 0; - switch(row_info->eval.irtree.mode) + switch(row->eval.irtree.mode) { default:{}break; case E_Mode_Offset: { - CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(row_info->eval.space); - if(row_info->eval.space.kind == RD_EvalSpaceKind_CtrlEntity && space_entity->kind == CTRL_EntityKind_Process) + CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(row->eval.space); + if(row->eval.space.kind == RD_EvalSpaceKind_CtrlEntity && space_entity->kind == CTRL_EntityKind_Process) { - U64 size = e_type_byte_size_from_key(row_info->eval.irtree.type_key); + U64 size = e_type_byte_size_from_key(row->eval.irtree.type_key); size = Min(size, 64); - Rng1U64 vaddr_rng = r1u64(row_info->eval.value.u64, row_info->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, space_entity->handle, vaddr_rng, rd_state->frame_eval_memread_endt_us); for(U64 idx = 0; idx < (slice.data.size+63)/64; idx += 1) { @@ -5150,32 +3881,38 @@ rd_view_ui(Rng2F32 rect) //////////////////// //- rjf: draw start of cache lines in expansions // - if(row_info->eval.space.kind == RD_EvalSpaceKind_CtrlEntity && row_info->view_ui_rule == &rd_nil_view_ui_rule) + if(row->eval.space.kind == RD_EvalSpaceKind_CtrlEntity && row_info->view_ui_rule == &rd_nil_view_ui_rule) { - U64 row_offset = row_info->eval.value.u64; - if((row_info->eval.irtree.mode == E_Mode_Offset || row_info->eval.irtree.mode == E_Mode_Null) && - row_offset%64 == 0 && row_depth > 0) + CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(row->eval.space); + if(space_entity->kind == CTRL_EntityKind_Process) { - ui_set_next_fixed_x(0); - ui_set_next_fixed_y(0); - ui_set_next_fixed_height(ui_top_font_size()*0.2f); - ui_set_next_tag(str8_lit("pop")); - ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawBackground, ui_key_zero()); + U64 row_offset = row->eval.value.u64; + if((row->eval.irtree.mode == E_Mode_Offset || row->eval.irtree.mode == E_Mode_Null) && + row_offset%64 == 0 && row_depth > 0) + { + ui_set_next_fixed_x(0); + ui_set_next_fixed_y(0); + ui_set_next_fixed_height(ui_top_font_size()*0.2f); + ui_set_next_tag(str8_lit("pop")); + ui_build_box_from_key(UI_BoxFlag_Floating|UI_BoxFlag_DrawBackground, ui_key_zero()); + } } } ////////////// //- rjf: draw mid-row cache line boundaries in expansions // - if(row_info->eval.space.kind == RD_EvalSpaceKind_CtrlEntity && row_info->view_ui_rule == &rd_nil_view_ui_rule) + if(row->eval.space.kind == RD_EvalSpaceKind_CtrlEntity && row_info->view_ui_rule == &rd_nil_view_ui_rule) { - if((row_info->eval.irtree.mode == E_Mode_Offset || row_info->eval.irtree.mode == E_Mode_Null) && - row_info->eval.value.u64%64 != 0 && + CTRL_Entity *space_entity = rd_ctrl_entity_from_eval_space(row->eval.space); + if(space_entity->kind == CTRL_EntityKind_Process && + (row->eval.irtree.mode == E_Mode_Offset || row->eval.irtree.mode == E_Mode_Null) && + row->eval.value.u64%64 != 0 && row_depth > 0 && !row_expanded) { - U64 next_off = (row_info->eval.value.u64 + e_type_byte_size_from_key(row_info->eval.irtree.type_key)); - if(next_off%64 != 0 && row_info->eval.value.u64/64 < next_off/64) + U64 next_off = (row->eval.value.u64 + e_type_byte_size_from_key(row->eval.irtree.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(row_height_px - ui_top_font_size()*0.5f); @@ -5291,7 +4028,7 @@ rd_view_ui(Rng2F32 rect) RD_Cfg *root = rd_immediate_cfg_from_keyf("view_%I64x_%I64x", rd_regs()->view, row_hash); RD_Cfg *view = rd_cfg_child_from_string_or_alloc(root, cell_info.view_ui_rule->name); RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(view, str8_lit("expression")); - rd_cfg_new(expr, e_string_from_expr(scratch.arena, cell_info.eval.exprs.last)); + rd_cfg_new(expr, e_string_from_expr(scratch.arena, cell_info.eval.expr)); rd_cfg_new(view, str8_lit("selected")); RD_RegsScope(.view = view->id, .file_path = rd_file_path_from_eval(scratch.arena, cell_info.eval)) UI_PermissionFlags(UI_PermissionFlag_Clicks|UI_PermissionFlag_ScrollX) @@ -5543,12 +4280,12 @@ rd_view_ui(Rng2F32 rect) case CTRL_EntityKind_Thread:{RD_RegsScope(.thread = cell_info.entity->handle) rd_drag_begin(RD_RegSlot_Thread);}break; } } - else if(row_info->eval.space.kind == RD_EvalSpaceKind_CtrlEntity || - row_info->eval.space.kind == E_SpaceKind_FileSystem || - row_info->eval.space.kind == E_SpaceKind_File || - row_info->eval.space.kind == E_SpaceKind_Null) + else if(row->eval.space.kind == RD_EvalSpaceKind_CtrlEntity || + row->eval.space.kind == E_SpaceKind_FileSystem || + row->eval.space.kind == E_SpaceKind_File || + row->eval.space.kind == E_SpaceKind_Null) { - RD_RegsScope(.expr = e_string_from_expr(scratch.arena, row_info->eval.exprs.last), + RD_RegsScope(.expr = e_string_from_expr(scratch.arena, row->eval.expr), .view_rule = ev_view_rule_from_key(rd_view_eval_view(), row->key)) rd_drag_begin(RD_RegSlot_Expr); } @@ -5583,8 +4320,8 @@ rd_view_ui(Rng2F32 rect) // rjf: has a command name? -> push command else if(cell_info.cmd_name.size != 0) { - CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(row_info->eval.space); - RD_Cfg *cfg = rd_cfg_from_eval_space(row_info->eval.space); + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(row->eval.space); + RD_Cfg *cfg = rd_cfg_from_eval_space(row->eval.space); RD_RegsScope(.cfg = cfg->id, .ctrl_entity = entity->handle) { if(cfg != &rd_nil_cfg || entity != &ctrl_entity_nil) @@ -7537,7 +6274,7 @@ rd_window_frame(void) EV_BlockTree predicted_block_tree = {0}; RD_RegsScope(.view = view->id) { - predicted_block_tree = ev_block_tree_from_exprs(scratch.arena, rd_view_eval_view(), str8_zero(), hover_eval.exprs); + predicted_block_tree = ev_block_tree_from_expr(scratch.arena, rd_view_eval_view(), str8_zero(), hover_eval.expr); } F32 row_height_px = ui_top_px_height(); U64 max_row_count = (U64)floor_f32(ui_top_font_size()*10.f / row_height_px); @@ -7689,7 +6426,7 @@ rd_window_frame(void) { Vec2F32 content_rect_center = center_2f32(content_rect); Vec2F32 content_rect_dim = dim_2f32(content_rect); - EV_BlockTree predicted_block_tree = ev_block_tree_from_exprs(scratch.arena, rd_view_eval_view(), rd_view_query_input(), query_eval.exprs); + EV_BlockTree predicted_block_tree = ev_block_tree_from_expr(scratch.arena, rd_view_eval_view(), rd_view_query_input(), query_eval.expr); F32 query_width_px = floor_f32(content_rect_dim.x * 0.35f); F32 max_query_height_px = content_rect_dim.y*0.8f; F32 query_height_px = max_query_height_px; @@ -10408,6 +9145,7 @@ rd_window_frame(void) //////////////////////////////// //~ rjf: Eval Visualization +#if 0 // TODO(rjf): @eval internal F32 rd_append_value_strings_from_eval(Arena *arena, String8 filter, EV_StringFlags flags, U32 default_radix, FNT_Tag font, F32 font_size, F32 max_size, S32 depth, E_Eval root_eval, E_Eval eval, String8List *out) { @@ -10448,9 +9186,9 @@ rd_append_value_strings_from_eval(Arena *arena, String8 filter, EV_StringFlags f } //- rjf: force no_string, if we are looking at padding members - if(eval.exprs.last->kind == E_ExprKind_MemberAccess) + if(eval.expr->kind == E_ExprKind_MemberAccess) { - E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, eval.exprs.last->first); + E_IRTreeAndType irtree = e_irtree_and_type_from_expr(scratch.arena, eval.expr->first); E_TypeKey struct_type = irtree.type_key; for(B32 done = 0; !done;) { @@ -10471,7 +9209,7 @@ rd_append_value_strings_from_eval(Arena *arena, String8 filter, EV_StringFlags f break; } } - E_Member member = e_type_member_from_key_name__cached(struct_type, eval.exprs.last->last->string); + E_Member member = e_type_member_from_key_name__cached(struct_type, eval.expr->first->next->string); if(member.kind == E_MemberKind_Padding) { no_string = 1; @@ -10640,7 +9378,7 @@ rd_append_value_strings_from_eval(Arena *arena, String8 filter, EV_StringFlags f { if(type->count == 1) { - E_Expr *deref_expr = e_expr_ref_deref(scratch.arena, eval.exprs.last); + 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 += rd_append_value_strings_from_eval(arena, filter, flags, radix, font, font_size, max_size-space_taken, depth+1, root_eval, deref_eval, out); } @@ -10877,6 +9615,7 @@ rd_value_string_from_eval(Arena *arena, String8 filter, EV_StringFlags flags, U3 scratch_end(scratch); return result; } +#endif internal String8 rd_value_string_from_eval_NEW(Arena *arena, String8 filter, EV_StringParams *params, FNT_Tag font, F32 font_size, F32 max_size, E_Eval eval) @@ -13540,26 +12279,33 @@ rd_frame(void) ctx->member_map = d_query_cached_member_map_from_dbgi_key_voff(&primary_dbgi_key, rip_voff); ctx->macro_map = push_array(scratch.arena, E_String2ExprMap, 1); ctx->macro_map[0] = e_string2expr_map_make(scratch.arena, 512); +#if 0 // TODO(rjf): @eval ctx->lookup_rule_map = push_array(scratch.arena, E_LookupRuleMap, 1); ctx->lookup_rule_map[0] = e_lookup_rule_map_make(scratch.arena, 512); ctx->irgen_rule_map = push_array(scratch.arena, E_IRGenRuleMap, 1); ctx->irgen_rule_map[0] = e_irgen_rule_map_make(scratch.arena, 512); +#endif ctx->auto_hook_map = push_array(scratch.arena, E_AutoHookMap, 1); ctx->auto_hook_map[0] = e_auto_hook_map_make(scratch.arena, 512); //- rjf: cache meta name -> type key correllation rd_state->meta_name2type_map = push_array(rd_frame_arena(), E_String2TypeKeyMap, 1); rd_state->meta_name2type_map[0] = e_string2typekey_map_make(rd_frame_arena(), 256); +#if 0 // TODO(rjf): @eval for EachElement(idx, rd_name_schema_info_table) { String8 name = rd_name_schema_info_table[idx].name; - E_TypeKey type_key = e_type_key_cons(.name = name, .kind = E_TypeKind_Set); + E_TypeKey type_key = e_type_key_cons(.name = name, + .kind = E_TypeKind_Set, + .access = E_TYPE_ACCESS_FUNCTION_NAME(schema), + .expand = + { + .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(schema), + .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(schema), + }); e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, name, type_key); - e_lookup_rule_map_insert_new(scratch.arena, ctx->lookup_rule_map, name, - .info = E_LOOKUP_INFO_FUNCTION_NAME(schema), - .range = E_LOOKUP_RANGE_FUNCTION_NAME(schema), - .access = E_LOOKUP_ACCESS_FUNCTION_NAME(schema)); } +#endif //- rjf: add macros for evallable top-level config trees String8 evallable_cfg_names[] = @@ -13681,30 +12427,39 @@ rd_frame(void) { String8 collection_name = str8_lit("watches"); E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafOffset, 0); - expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = collection_name, .flags = E_TypeFlag_EditableChildren); expr->space = e_space_make(RD_EvalSpaceKind_MetaQuery); + expr->type_key = e_type_key_cons(.kind = E_TypeKind_Set, .name = collection_name, .flags = E_TypeFlag_EditableChildren, + .expand = + { + .info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(watches), + .range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(watches), + .id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(watches), + .num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(watches), + }); e_string2expr_map_insert(scratch.arena, ctx->macro_map, collection_name, expr); - e_lookup_rule_map_insert_new(scratch.arena, ctx->lookup_rule_map, collection_name, - .info = E_LOOKUP_INFO_FUNCTION_NAME(watches), - .range = E_LOOKUP_RANGE_FUNCTION_NAME(watches), - .id_from_num = E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(watches), - .num_from_id = E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(watches)); } - //- rjf: add lookup rules for queries + //- rjf: add types for queries { - e_lookup_rule_map_insert_new(scratch.arena, ctx->lookup_rule_map, str8_lit("environment"), - .info = E_LOOKUP_INFO_FUNCTION_NAME(environment), - .access = E_LOOKUP_ACCESS_FUNCTION_NAME(environment), - .range = E_LOOKUP_RANGE_FUNCTION_NAME(environment), - .id_from_num = E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(environment), - .num_from_id = E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(environment)); - e_lookup_rule_map_insert_new(scratch.arena, ctx->lookup_rule_map, str8_lit("call_stack"), - .info = E_LOOKUP_INFO_FUNCTION_NAME(call_stack), - .access = E_LOOKUP_ACCESS_FUNCTION_NAME(call_stack)); +#if 0 // TODO(rjf): @eval + e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("environment"), + e_type_key_cons(.kind = E_TypeKind_Set, + .name = str8_lit("environment"), + .flags = E_TypeFlag_EditableChildren, + .expand = + { + .info = E_LOOKUP_INFO_FUNCTION_NAME(environment), + .range = E_LOOKUP_RANGE_FUNCTION_NAME(environment), + .id_from_num = E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(environment), + .num_from_id = E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(environment), + })); + e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("call_stack"), + e_type_key_cons(.kind = E_TypeKind_Set, .name = str8_lit("call_stack"))); +#endif } //- rjf: add macro for collections with specific lookup rules (but no unique id rules) +#if 0 // TODO(rjf): @eval { struct { @@ -13730,8 +12485,10 @@ rd_frame(void) .range = collection_infos[idx].lookup_range); } } +#endif //- rjf: add macros for debug info table collections +#if 0 // TODO(rjf): @eval String8 debug_info_table_collection_names[] = { str8_lit_comp("procedures"), @@ -13813,6 +12570,7 @@ rd_frame(void) .access = E_LOOKUP_ACCESS_FUNCTION_NAME(commands), .range = E_LOOKUP_RANGE_FUNCTION_NAME(commands)); } +#endif //- rjf: add macro for output log { diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index d61f709e..32780f50 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -1005,8 +1005,10 @@ internal void rd_window_frame(void); //////////////////////////////// //~ rjf: Eval Visualization +#if 0 // TODO(rjf): @eval internal F32 rd_append_value_strings_from_eval(Arena *arena, String8 filter, EV_StringFlags flags, U32 default_radix, FNT_Tag font, F32 font_size, F32 max_size, S32 depth, E_Eval root_eval, E_Eval eval, String8List *out); internal String8 rd_value_string_from_eval(Arena *arena, String8 filter, EV_StringFlags flags, U32 default_radix, FNT_Tag font, F32 font_size, F32 max_size, E_Eval eval); +#endif internal String8 rd_value_string_from_eval_NEW(Arena *arena, String8 filter, EV_StringParams *params, FNT_Tag font, F32 font_size, F32 max_size, E_Eval eval); //////////////////////////////// diff --git a/src/raddbg/raddbg_eval.c b/src/raddbg/raddbg_eval.c new file mode 100644 index 00000000..275b7cd2 --- /dev/null +++ b/src/raddbg/raddbg_eval.c @@ -0,0 +1,1274 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +//////////////////////////////// +//~ rjf: `commands` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(commands) +{ + E_TypeExpandInfo result = {0}; + if(filter.size != 0) + { + Temp scratch = scratch_begin(&arena, 1); + String8List cmd_names = {0}; + for EachNonZeroEnumVal(RD_CmdKind, k) + { + RD_CmdKindInfo *info = &rd_cmd_kind_info_table[k]; + String8 name = info->string; + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, name); + if(matches.count == matches.needle_part_count) + { + str8_list_push(scratch.arena, &cmd_names, name); + } + } + String8Array *accel = push_array(arena, String8Array, 1); + *accel = str8_array_from_list(arena, &cmd_names); + result.user_data = accel; + result.expr_count = accel->count; + scratch_end(scratch); + } + else + { + result.expr_count = RD_CmdKind_COUNT; + } + return result; +} + +E_TYPE_ACCESS_FUNCTION_DEF(commands) +{ + E_IRTreeAndType result = {&e_irnode_nil}; + if(expr->kind == E_ExprKind_MemberAccess) + { + String8 cmd_name = expr->first->next->string; + result.type_key = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("command")); + result.mode = E_Mode_Value; + result.root = e_irtree_set_space(arena, e_space_make(RD_EvalSpaceKind_MetaCmd), e_irtree_const_u(arena, e_id_from_string(cmd_name))); + } + return result; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(commands) +{ + U64 out_idx = 0; + if(user_data != 0) + { + String8Array *accel = (String8Array *)user_data; + for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) + { + String8 cmd_name = accel->v[idx]; + E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); + expr->type_key = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("command")); + expr->space = e_space_make(RD_EvalSpaceKind_MetaCmd); + expr->value.u64 = e_id_from_string(cmd_name); + exprs_out[out_idx] = expr; + } + } + else + { + for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) + { + RD_CmdKind cmd_kind = (RD_CmdKind)idx; + String8 cmd_name = rd_cmd_kind_info_table[cmd_kind].string; + E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); + expr->type_key = e_type_key_cons(.kind = E_TypeKind_U64, .name = str8_lit("command")); + expr->space = e_space_make(RD_EvalSpaceKind_MetaCmd); + expr->value.u64 = e_id_from_string(cmd_name); + exprs_out[out_idx] = expr; + } + } +} + +//////////////////////////////// +//~ rjf: `watches` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(watches) +{ + E_TypeExpandInfo result = {0}; + Temp scratch = scratch_begin(&arena, 1); + { + RD_CfgList cfgs_list = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("watch")); + RD_CfgList cfgs_list__filtered = cfgs_list; + if(filter.size != 0) + { + MemoryZeroStruct(&cfgs_list__filtered); + for(RD_CfgNode *n = cfgs_list.first; n != 0; n = n->next) + { + String8 expr = rd_expr_from_cfg(n->v); + B32 passes_filter = 1; + if(filter.size != 0) + { + E_Eval eval = e_eval_from_string(scratch.arena, expr); + E_Type *type = e_type_from_key__cached(eval.irtree.type_key); + if(type->kind != E_TypeKind_Set) + { + passes_filter = 0; + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, expr); + if(matches.count == matches.needle_part_count) + { + passes_filter = 1; + } + } + } + if(passes_filter) + { + rd_cfg_list_push(scratch.arena, &cfgs_list__filtered, n->v); + } + } + } + RD_CfgArray *cfgs = push_array(arena, RD_CfgArray, 1); + cfgs[0] = rd_cfg_array_from_list(arena, &cfgs_list__filtered); + result.user_data = cfgs; + result.expr_count = cfgs->count + 1; + } + scratch_end(scratch); + return result; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(watches) +{ + RD_CfgArray *cfgs = (RD_CfgArray *)user_data; + Rng1U64 legal_idx_range = r1u64(0, cfgs->count); + Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); + U64 read_range_count = dim_1u64(read_range); + for(U64 idx = 0; idx < read_range_count; idx += 1) + { + U64 cfg_idx = read_range.min + idx; + if(cfg_idx < cfgs->count) + { + String8 expr_string = rd_cfg_child_from_string(cfgs->v[cfg_idx], str8_lit("expression"))->first->string; + exprs_out[idx] = e_parse_expr_from_text(arena, expr_string).exprs.first; + exprs_strings_out[idx] = push_str8_copy(arena, expr_string); + } + } +} + +E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(watches) +{ + U64 id = 0; + RD_CfgArray *cfgs = (RD_CfgArray *)user_data; + if(1 <= num && num <= cfgs->count) + { + U64 idx = (num-1); + id = cfgs->v[idx]->id; + } + else if(num == cfgs->count+1) + { + id = max_U64; + } + return id; +} + +E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(watches) +{ + U64 num = 0; + RD_CfgArray *cfgs = (RD_CfgArray *)user_data; + if(id != 0 && id != max_U64) + { + for EachIndex(idx, cfgs->count) + { + if(cfgs->v[idx]->id == id) + { + num = idx+1; + break; + } + } + } + else if(id == max_U64) + { + num = cfgs->count + 1; + } + return num; +} + +//////////////////////////////// +//~ rjf: `locals` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(locals) +{ + E_TypeExpandInfo result = {0}; + Temp scratch = scratch_begin(&arena, 1); + { + E_String2NumMapNodeArray nodes = e_string2num_map_node_array_from_map(scratch.arena, e_ir_state->ctx->locals_map); + e_string2num_map_node_array_sort__in_place(&nodes); + String8List exprs_filtered = {0}; + for EachIndex(idx, nodes.count) + { + String8 local_expr_string = nodes.v[idx]->string; + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, local_expr_string); + if(matches.count == matches.needle_part_count) + { + str8_list_push(scratch.arena, &exprs_filtered, local_expr_string); + } + } + String8Array *accel = push_array(arena, String8Array, 1); + *accel = str8_array_from_list(arena, &exprs_filtered); + result.user_data = accel; + result.expr_count = accel->count; + } + scratch_end(scratch); + return result; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(locals) +{ + String8Array *accel = (String8Array *)user_data; + Rng1U64 legal_idx_range = r1u64(0, accel->count); + Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); + U64 read_range_count = dim_1u64(read_range); + for(U64 idx = 0; idx < read_range_count; idx += 1) + { + String8 expr_string = accel->v[read_range.min + idx]; + exprs_out[idx] = e_parse_expr_from_text(arena, expr_string).exprs.last; + exprs_strings_out[idx] = push_str8_copy(arena, expr_string); + } +} + +//////////////////////////////// +//~ rjf: `registers` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(registers) +{ + Temp scratch = scratch_begin(&arena, 1); + CTRL_Entity *thread = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->thread); + Arch arch = thread->arch; + U64 reg_count = regs_reg_code_count_from_arch(arch); + U64 alias_count = regs_alias_code_count_from_arch(arch); + String8 *reg_strings = regs_reg_code_string_table_from_arch(arch); + String8 *alias_strings = regs_alias_code_string_table_from_arch(arch); + String8List exprs_list = {0}; + for(U64 idx = 1; idx < reg_count; idx += 1) + { + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, reg_strings[idx]); + if(matches.count == matches.needle_part_count) + { + str8_list_push(scratch.arena, &exprs_list, reg_strings[idx]); + } + } + for(U64 idx = 1; idx < alias_count; idx += 1) + { + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, alias_strings[idx]); + if(matches.count == matches.needle_part_count) + { + str8_list_push(scratch.arena, &exprs_list, alias_strings[idx]); + } + } + String8Array *accel = push_array(arena, String8Array, 1); + *accel = str8_array_from_list(arena, &exprs_list); + E_TypeExpandInfo info = {accel, accel->count}; + scratch_end(scratch); + return info; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(registers) +{ + String8Array *accel = (String8Array *)user_data; + Rng1U64 legal_idx_range = r1u64(0, accel->count); + Rng1U64 read_range = intersect_1u64(legal_idx_range, idx_range); + U64 read_range_count = dim_1u64(read_range); + for(U64 idx = 0; idx < read_range_count; idx += 1) + { + String8 register_name = accel->v[read_range.min + idx]; + String8 register_expr = push_str8f(arena, "reg:%S", register_name); + exprs_strings_out[idx] = register_name; + exprs_out[idx] = e_parse_expr_from_text(arena, register_expr).exprs.last; + } +} + +//////////////////////////////// +//~ rjf: Schema Type Hooks + +#if 0 // TODO(rjf): @eval + +E_TYPE_ACCESS_FUNCTION_DEF(schema) +{ + RD_SchemaLookupAccel *accel = (RD_SchemaLookupAccel *)user_data; + E_IRTreeAndType irtree = {&e_irnode_nil}; + if(kind == E_ExprKind_MemberAccess) + { + MD_Node *child_schema = &md_nil_node; + for MD_EachNode(child, accel->schema->first) + { + if(str8_match(child->string, rhs->string, 0)) + { + child_schema = child; + break; + } + } + if(child_schema != &md_nil_node) + { + RD_Cfg *cfg = accel->cfg; + CTRL_Entity *entity = accel->entity; + RD_Cfg *child = rd_cfg_child_from_string(cfg, child_schema->string); + E_TypeKey child_type_key = zero_struct; + if(0){} + + //- rjf: ctrl entity members + else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("label"), 0)) + { + child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, E_TypeFlag_IsCodeText); + } + else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("exe"), 0)) + { + child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, E_TypeFlag_IsPathText); + } + else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("dbg"), 0)) + { + CTRL_Entity *dbg = ctrl_entity_child_from_kind(entity, CTRL_EntityKind_DebugInfoPath); + child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), dbg->string.size, E_TypeFlag_IsPathText); + } + + //- rjf: cfg members + else if(str8_match(child_schema->first->string, str8_lit("code_string"), 0)) + { + child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsCodeText); + } + else if(str8_match(child_schema->first->string, str8_lit("path"), 0)) + { + child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPathText); + } + else if(str8_match(child_schema->first->string, str8_lit("path_pt"), 0)) + { + Temp scratch = scratch_begin(&arena, 1); + String8 string = push_str8f(scratch.arena, "%S%s%S%s%S", child->first->string, child->first->string.size ? ":" : "", child->first->first->string, child->first->first->first->string.size ? ":" : "", child->first->first->first->string); + child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), string.size, E_TypeFlag_IsPathText); + scratch_end(scratch); + } + else if(str8_match(child_schema->first->string, str8_lit("string"), 0)) + { + child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPlainText); + } + + //- rjf: catchall cases + else if(str8_match(child_schema->first->string, str8_lit("u64"), 0)) + { + child_type_key = e_type_key_basic(E_TypeKind_U64); + } + else if(str8_match(child_schema->first->string, str8_lit("bool"), 0)) + { + child_type_key = e_type_key_basic(E_TypeKind_Bool); + } + else if(str8_match(child_schema->first->string, str8_lit("vaddr_range"), 0)) + { + Temp scratch = scratch_begin(&arena, 1); + E_MemberList vaddr_range_members_list = {0}; + e_member_list_push_new(scratch.arena, &vaddr_range_members_list, .type_key = e_type_key_basic(E_TypeKind_U64), .name = str8_lit("min"), .off = 0); + e_member_list_push_new(scratch.arena, &vaddr_range_members_list, .type_key = e_type_key_basic(E_TypeKind_U64), .name = str8_lit("max"), .off = 8); + E_MemberArray vaddr_range_members = e_member_array_from_list(scratch.arena, &vaddr_range_members_list); + child_type_key = e_type_key_cons(.kind = E_TypeKind_Struct, .name = str8_lit("vaddr_range"), .count = vaddr_range_members.count, .members = vaddr_range_members.v); + scratch_end(scratch); + } + else if(str8_match(child_schema->first->string, str8_lit("query"), 0)) + { + child_type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, child_schema->string); + } + + //- rjf: evaluate + E_Space child_eval_space = zero_struct; + if(cfg != &rd_nil_cfg) + { + child_eval_space = e_space_make(RD_EvalSpaceKind_MetaCfg); + child_eval_space.u64s[0] = cfg->id; + child_eval_space.u64s[1] = e_id_from_string(child_schema->string); + } + else + { + child_eval_space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); + child_eval_space.u64s[2] = e_id_from_string(child_schema->string); + } + irtree.root = e_irtree_set_space(arena, child_eval_space, e_push_irnode(arena, RDI_EvalOp_ConstU64)); + irtree.type_key = child_type_key; + irtree.mode = E_Mode_Offset; + } + } + E_LookupAccess access = {irtree}; + return access; +} + +typedef struct RD_SchemaLookupAccel RD_SchemaLookupAccel; +struct RD_SchemaLookupAccel +{ + RD_Cfg *cfg; + CTRL_Entity *entity; + MD_Node *schema; + MD_Node **children; + U64 children_count; +}; + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(schema) +{ + E_TypeExpandInfo result = {0}; + { + Temp scratch = scratch_begin(&arena, 1); + + // rjf: unpack + E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs->root); + String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); + E_Interpretation interpret = e_interpret(bytecode); + E_TypeKey type_key = lhs->type_key; + E_Type *type = e_type_from_key__cached(type_key); + MD_Node *schema = rd_schema_from_name(type->name); + + // rjf: gather expansion children + typedef struct ExpandChildNode ExpandChildNode; + struct ExpandChildNode + { + ExpandChildNode *next; + MD_Node *n; + }; + ExpandChildNode *first_child_node = 0; + ExpandChildNode *last_child_node = 0; + U64 child_count = 0; + for MD_EachNode(child, schema->first) + { + if(!md_node_has_tag(child, str8_lit("no_expand"), 0)) + { + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, child->string); + if(matches.count == matches.needle_part_count) + { + ExpandChildNode *n = push_array(scratch.arena, ExpandChildNode, 1); + n->n = child; + SLLQueuePush(first_child_node, last_child_node, n); + child_count += 1; + } + } + } + + // rjf: flatten expansion member list + MD_Node **children = push_array(arena, MD_Node *, child_count); + { + U64 idx = 0; + for(ExpandChildNode *n = first_child_node; n != 0; n = n->next, idx += 1) + { + children[idx] = n->n; + } + } + + // rjf: build accelerator for lookups + RD_SchemaLookupAccel *accel = push_array(arena, RD_SchemaLookupAccel, 1); + accel->cfg = rd_cfg_from_eval_space(interpret.space); + accel->entity = rd_ctrl_entity_from_eval_space(interpret.space); + accel->schema = schema; + accel->children = children; + accel->children_count = child_count; + + // rjf: fill result + result.user_data = accel; + result.expr_count = child_count; + + scratch_end(scratch); + } + return result; +} + +E_LOOKUP_RANGE_FUNCTION_DEF(schema) +{ + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); + RD_SchemaLookupAccel *accel = (RD_SchemaLookupAccel *)user_data; + U64 out_idx = 0; + for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) + { + if(0 <= idx && idx < accel->children_count) + { + MD_Node *child_schema = accel->children[idx]; + exprs[out_idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, child_schema->string); + } + } +} + +//////////////////////////////// +//~ rjf: Config Collection Type Hooks + +typedef struct RD_CfgCollectionLookupAccel RD_CfgCollectionLookupAccel; +struct RD_CfgCollectionLookupAccel +{ + String8Array cmds; + RD_CfgArray cfgs; + Rng1U64 cmds_idx_range; + Rng1U64 cfgs_idx_range; +}; + +E_LOOKUP_INFO_FUNCTION_DEF(cfgs) +{ + E_LookupInfo result = {0}; + Temp scratch = scratch_begin(&arena, 1); + { + //- rjf: determine which cfg we'll use to scope the lookups + E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs->root); + String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); + E_Interpretation lhs_interp = e_interpret(lhs_bytecode); + RD_Cfg *scoping_cfg = rd_cfg_from_eval_space(lhs_interp.space); + + //- rjf: determine which kind of child we'll be gathering + E_TypeKey lhs_type_key = lhs->type_key; + E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); + String8 cfg_name = rd_singular_from_code_name_plural(lhs_type->name); + + //- rjf: gather cfgs + RD_CfgList cfgs_list = {0}; + if(scoping_cfg == &rd_nil_cfg) + { + cfgs_list = rd_cfg_top_level_list_from_string(scratch.arena, cfg_name); + } + else + { + cfgs_list = rd_cfg_child_list_from_string(scratch.arena, scoping_cfg, cfg_name); + } + + //- rjf: filter cfgs + RD_CfgList cfgs_list__filtered = cfgs_list; + if(filter.size != 0) + { + MemoryZeroStruct(&cfgs_list__filtered); + for(RD_CfgNode *n = cfgs_list.first; n != 0; n = n->next) + { + DR_FStrList fstrs = rd_title_fstrs_from_cfg(scratch.arena, n->v); + String8 string = dr_string_from_fstrs(scratch.arena, &fstrs); + FuzzyMatchRangeList fuzzy_matches = fuzzy_match_find(scratch.arena, filter, string); + if(fuzzy_matches.count == fuzzy_matches.needle_part_count) + { + rd_cfg_list_push(scratch.arena, &cfgs_list__filtered, n->v); + } + } + } + + //- rjf: gather commands + String8List cmds_list = {0}; + if(filter.size == 0) + { + MD_Node *schema = rd_schema_from_name(cfg_name); + MD_Node *collection_cmds_root = md_tag_from_string(schema, str8_lit("collection_commands"), 0); + for MD_EachNode(cmd, collection_cmds_root->first) + { + str8_list_push(arena, &cmds_list, cmd->string); + } + } + + //- rjf: package & fill + RD_CfgCollectionLookupAccel *accel = push_array(arena, RD_CfgCollectionLookupAccel, 1); + accel->cfgs = rd_cfg_array_from_list(arena, &cfgs_list__filtered); + accel->cmds = str8_array_from_list(arena, &cmds_list); + accel->cmds_idx_range = r1u64(0, accel->cmds.count); + accel->cfgs_idx_range = r1u64(accel->cmds_idx_range.max, accel->cmds_idx_range.max + accel->cfgs.count); + result.user_data = accel; + result.idxed_expr_count = accel->cfgs.count + accel->cmds.count; + } + scratch_end(scratch); + return result; +} + +E_LOOKUP_ACCESS_FUNCTION_DEF(cfgs) +{ + Temp scratch = scratch_begin(&arena, 1); + E_LookupAccess result = {{&e_irnode_nil}}; + RD_Cfg *cfg = &rd_nil_cfg; + if(kind == E_ExprKind_MemberAccess) + { + String8 rhs_name = rhs->string; + RD_CfgID id = 0; + if(str8_match(str8_prefix(rhs_name, 1), str8_lit("$"), 0) && + try_u64_from_str8_c_rules(str8_skip(rhs_name, 1), &id)) + { + cfg = rd_cfg_from_id(id); + } + } + else if(kind == E_ExprKind_ArrayIndex) + { + E_IRTreeAndType rhs_irtree = e_irtree_and_type_from_expr(scratch.arena, rhs); + E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); + String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); + E_Interpretation rhs_interp = e_interpret(rhs_bytecode); + E_Value rhs_value = rhs_interp.value; + U64 rhs_idx = rhs_value.u64; + RD_CfgCollectionLookupAccel *accel = (RD_CfgCollectionLookupAccel *)user_data; + if(0 <= rhs_idx && rhs_idx < accel->cfgs.count) + { + cfg = accel->cfgs.v[rhs_idx]; + } + } + if(cfg != &rd_nil_cfg) + { + E_Space cfg_space = rd_eval_space_from_cfg(cfg); + String8 cfg_name = cfg->string; + E_TypeKey cfg_type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, cfg_name); + result.irtree_and_type.root = e_irtree_set_space(arena, cfg_space, e_irtree_const_u(arena, 0)); + result.irtree_and_type.type_key = cfg_type_key; + result.irtree_and_type.mode = E_Mode_Offset; + } + scratch_end(scratch); + return result; +} + +E_LOOKUP_RANGE_FUNCTION_DEF(cfgs) +{ + RD_CfgCollectionLookupAccel *accel = (RD_CfgCollectionLookupAccel *)user_data; + Rng1U64 cmds_idx_range = accel->cmds_idx_range; + Rng1U64 cfgs_idx_range = accel->cfgs_idx_range; + U64 dst_idx = 0; + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); + + // rjf: fill commands + { + Rng1U64 read_range = intersect_1u64(cmds_idx_range, idx_range); + U64 read_count = dim_1u64(read_range); + E_Expr *commands = e_parse_expr_from_text(arena, str8_lit("query:commands")).exprs.last; + E_IRTreeAndType commands_irtree = e_irtree_and_type_from_expr(arena, commands); + for(U64 idx = 0; idx < read_count; idx += 1, dst_idx += 1) + { + String8 cmd_name = accel->cmds.v[idx + read_range.min - cmds_idx_range.min]; + exprs[dst_idx] = e_expr_irext_member_access(arena, commands, &commands_irtree, cmd_name); + } + } + + // rjf: fill cfgs + { + Rng1U64 read_range = intersect_1u64(cfgs_idx_range, idx_range); + U64 read_count = dim_1u64(read_range); + for(U64 idx = 0; idx < read_count; idx += 1, dst_idx += 1) + { + RD_Cfg *cfg = accel->cfgs.v[idx + read_range.min - cfgs_idx_range.min]; + exprs[dst_idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, push_str8f(arena, "$%I64d", cfg->id)); + } + } +} + +E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(cfgs) +{ + U64 id = 0; + RD_CfgCollectionLookupAccel *accel = (RD_CfgCollectionLookupAccel *)user_data; + if(num != 0) + { + U64 idx = num-1; + if(contains_1u64(accel->cfgs_idx_range, idx)) + { + RD_Cfg *cfg = accel->cfgs.v[idx - accel->cfgs_idx_range.min]; + id = cfg->id; + } + else if(contains_1u64(accel->cmds_idx_range, idx)) + { + id = num; + id |= (1ull<<63); + } + } + return id; +} + +E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(cfgs) +{ + U64 num = 0; + RD_CfgCollectionLookupAccel *accel = (RD_CfgCollectionLookupAccel *)user_data; + if(id != 0) + { + if(id & (1ull<<63)) + { + num = id; + num &= ~(1ull<<63); + } + else for EachIndex(idx, accel->cfgs.count) + { + if(accel->cfgs.v[idx]->id == id) + { + num = idx + accel->cfgs_idx_range.min + 1; + break; + } + } + } + return num; +} + +//////////////////////////////// +//~ rjf: `call_stack` Type Hooks + +typedef struct RD_CallStackLookupAccel RD_CallStackLookupAccel; +struct RD_CallStackLookupAccel +{ + Arch arch; + CTRL_Handle process; + CTRL_CallStack call_stack; +}; + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(call_stack) +{ + E_TypeExpandInfo result = {0}; + Temp scratch = scratch_begin(&arena, 1); + { + RD_CallStackLookupAccel *accel = push_array(arena, RD_CallStackLookupAccel, 1); + E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs->root); + String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); + E_Interpretation interp = e_interpret(bytecode); + CTRL_Entity *entity = rd_ctrl_entity_from_eval_space(interp.space); + if(entity->kind == CTRL_EntityKind_Thread) + { + CTRL_Entity *process = ctrl_process_from_entity(entity); + CTRL_Unwind base_unwind = d_query_cached_unwind_from_thread(entity); + accel->arch = entity->arch; + accel->process = process->handle; + accel->call_stack = ctrl_call_stack_from_unwind(arena, rd_state->frame_di_scope, process, &base_unwind); + result.expr_count = accel->call_stack.count; + } + result.user_data = accel; + } + scratch_end(scratch); + return result; +} + +E_TYPE_ACCESS_FUNCTION_DEF(call_stack) +{ + E_LookupAccess result = {{&e_irnode_nil}}; + if(kind == E_ExprKind_ArrayIndex) + { + Temp scratch = scratch_begin(&arena, 1); + E_IRTreeAndType rhs_irtree = e_irtree_and_type_from_expr(scratch.arena, rhs); + E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); + String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); + E_Interpretation rhs_interp = e_interpret(rhs_bytecode); + E_Value rhs_value = rhs_interp.value; + RD_CallStackLookupAccel *accel = (RD_CallStackLookupAccel *)user_data; + CTRL_CallStack *call_stack = &accel->call_stack; + if(0 <= rhs_value.u64 && rhs_value.u64 < call_stack->count) + { + CTRL_Entity *process = ctrl_entity_from_handle(d_state->ctrl_entity_store, accel->process); + CTRL_CallStackFrame *f = &call_stack->frames[rhs_value.u64]; + result.irtree_and_type.root = e_irtree_set_space(arena, rd_eval_space_from_ctrl_entity(process, RD_EvalSpaceKind_CtrlEntity), e_irtree_const_u(arena, regs_rip_from_arch_block(accel->arch, f->regs))); + result.irtree_and_type.type_key = e_type_key_cons(.arch = process->arch, .kind = E_TypeKind_Ptr, .direct_key = e_type_key_basic(E_TypeKind_Function), .count = 1, .depth = f->inline_depth); + result.irtree_and_type.mode = E_Mode_Value; + } + scratch_end(scratch); + } + return result; +} + +//////////////////////////////// +//~ rjf: `environment` Type Hooks + +E_TYPE_ACCESS_FUNCTION_DEF(environment) +{ + E_LookupAccess result = {{&e_irnode_nil}}; + if(kind == E_ExprKind_ArrayIndex) + { + Temp scratch = scratch_begin(&arena, 1); + RD_CfgArray *cfgs = (RD_CfgArray *)user_data; + E_IRTreeAndType rhs_irtree = e_irtree_and_type_from_expr(scratch.arena, rhs); + E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); + String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); + E_Interpretation rhs_interp = e_interpret(rhs_bytecode); + E_Value rhs_value = rhs_interp.value; + if(0 <= rhs_value.u64 && rhs_value.u64 < cfgs->count) + { + RD_Cfg *cfg = cfgs->v[rhs_value.u64]; + result.irtree_and_type.root = e_irtree_set_space(arena, rd_eval_space_from_cfg(cfg), e_irtree_const_u(arena, 0)); + result.irtree_and_type.type_key = e_type_key_cons_ptr(arch_from_context(), e_type_key_basic(E_TypeKind_U8), 1, E_TypeFlag_IsCodeText); + result.irtree_and_type.mode = E_Mode_Offset; + } + scratch_end(scratch); + } + return result; +} + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(environment) +{ + E_TypeExpandInfo result = {0}; + Temp scratch = scratch_begin(&arena, 1); + { + E_OpList oplist = e_oplist_from_irtree(scratch.arena, lhs->root); + String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist); + E_Interpretation interpret = e_interpret(bytecode); + RD_Cfg *target = rd_cfg_from_eval_space(interpret.space); + RD_CfgList env_strings = {0}; + for(RD_Cfg *child = target->first; child != &rd_nil_cfg; child = child->next) + { + if(str8_match(child->string, str8_lit("environment"), 0)) + { + rd_cfg_list_push(scratch.arena, &env_strings, child); + } + } + RD_CfgArray *accel = push_array(arena, RD_CfgArray, 1); + *accel = rd_cfg_array_from_list(arena, &env_strings); + result.user_data = accel; + result.idxed_expr_count = accel->count + 1; + } + scratch_end(scratch); + return result; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(environment) +{ + RD_CfgArray *cfgs = (RD_CfgArray *)user_data; + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); + Rng1U64 legal_idx_range = r1u64(0, cfgs->count); + Rng1U64 read_range = intersect_1u64(idx_range, legal_idx_range); + U64 read_range_count = dim_1u64(read_range); + for(U64 idx = 0; idx < read_range_count; idx += 1) + { + U64 cfg_idx = read_range.min + idx; + if(cfg_idx < cfgs->count) + { + exprs[idx] = e_expr_irext_array_index(arena, lhs, &lhs_irtree, cfg_idx); + } + } +} + +E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(environment) +{ + U64 id = 0; + RD_CfgArray *cfgs = (RD_CfgArray *)user_data; + if(1 <= num && num <= cfgs->count) + { + U64 idx = (num-1); + id = cfgs->v[idx]->id; + } + else if(num == cfgs->count+1) + { + id = max_U64; + } + return id; +} + +E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(environment) +{ + U64 num = 0; + RD_CfgArray *cfgs = (RD_CfgArray *)user_data; + if(id != 0 && id != max_U64) + { + for EachIndex(idx, cfgs->count) + { + if(cfgs->v[idx]->id == id) + { + num = idx+1; + break; + } + } + } + else if(id == max_U64) + { + num = cfgs->count + 1; + } + return num; +} + +//////////////////////////////// +//~ rjf: `unattached_processes` Type Hooks + +typedef struct RD_UnattachedProcessesAccel RD_UnattachedProcessesAccel; +struct RD_UnattachedProcessesAccel +{ + DMN_ProcessInfo *infos; + CTRL_Entity **machines; + U64 infos_count; +}; + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(unattached_processes) +{ + E_TypeExpandInfo info = {0}; + { + Temp scratch = scratch_begin(&arena, 1); + + //- rjf: evaluate lhs machine, if we have one + E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs->root); + String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); + E_Interpretation lhs_interp = e_interpret(lhs_bytecode); + CTRL_Entity *lhs_entity = rd_ctrl_entity_from_eval_space(lhs_interp.space); + + //- rjf: gather all machines we're searching through + CTRL_EntityList machines = {0}; + if(lhs_entity->kind == CTRL_EntityKind_Machine) + { + ctrl_entity_list_push(scratch.arena, &machines, lhs_entity); + } + else + { + machines = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Machine); + } + + //- rjf: gather system processes from this machine + typedef struct Node Node; + struct Node + { + Node *next; + CTRL_Entity *machine; + DMN_ProcessInfo info; + }; + Node *first = 0; + Node *last = 0; + U64 count = 0; + for(CTRL_EntityNode *n = machines.first; n != 0; n = n->next) + { + CTRL_Entity *machine = n->v; + DMN_ProcessIter iter = {0}; + dmn_process_iter_begin(&iter); + for(DMN_ProcessInfo info = {0}; dmn_process_iter_next(scratch.arena, &iter, &info);) + { + B32 passes_filter = 1; + if(filter.size != 0) + { + passes_filter = 0; + FuzzyMatchRangeList name_matches = fuzzy_match_find(scratch.arena, filter, info.name); + FuzzyMatchRangeList pid_matches = fuzzy_match_find(scratch.arena, filter, push_str8f(scratch.arena, "%I64u", info.pid)); + if(name_matches.count == name_matches.needle_part_count || pid_matches.count == pid_matches.needle_part_count) + { + passes_filter = 1; + } + } + if(passes_filter) + { + Node *node = push_array(scratch.arena, Node, 1); + SLLQueuePush(first, last, node); + node->machine = machine; + node->info = info; + count += 1; + } + } + dmn_process_iter_end(&iter); + } + + //- rjf: list -> array + U64 infos_count = count; + DMN_ProcessInfo *infos = push_array(arena, DMN_ProcessInfo, infos_count); + CTRL_Entity **infos_machines = push_array(arena, CTRL_Entity *, infos_count); + { + U64 idx = 0; + for(Node *n = first; n != 0; n = n->next, idx += 1) + { + infos[idx] = n->info; + infos[idx].name = push_str8_copy(arena, infos[idx].name); + infos_machines[idx] = n->machine; + } + } + + //- rjf: build accelerator + RD_UnattachedProcessesAccel *accel = push_array(arena, RD_UnattachedProcessesAccel, 1); + accel->infos = infos; + accel->infos_count = infos_count; + accel->machines = infos_machines; + info.user_data = accel; + info.idxed_expr_count = infos_count; + scratch_end(scratch); + } + return info; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(unattached_processes) +{ + RD_UnattachedProcessesAccel *accel = (RD_UnattachedProcessesAccel *)user_data; + U64 out_idx = 0; + E_TypeKey unattached_process_type = e_type_key_cons(.kind = E_TypeKind_U128, .name = str8_lit("unattached_process")); + for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) + { + E_Expr *expr = e_push_expr(arena, E_ExprKind_LeafValue, 0); + expr->type_key = unattached_process_type; + expr->value.u128.u64[0] = accel->infos[idx].pid; + expr->value.u128.u64[1] = e_id_from_string(accel->infos[idx].name); + expr->space = rd_eval_space_from_ctrl_entity(accel->machines[idx], RD_EvalSpaceKind_MetaUnattachedProcess); + exprs_out[out_idx] = expr; + } +} + +//////////////////////////////// +//~ rjf: Control Entity List Type Hooks (`processes`, `threads`, etc.) + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(ctrl_entities) +{ + E_TypeExpandInfo result = {0}; + Temp scratch = scratch_begin(&arena, 1); + { + //- rjf: determine which entity we're looking under + E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs->root); + String8 lhs_bytecode = e_bytecode_from_oplist(scratch.arena, &lhs_oplist); + E_Interpretation lhs_interp = e_interpret(lhs_bytecode); + CTRL_Entity *scoping_entity = &ctrl_entity_nil; + if(lhs_interp.space.kind == RD_EvalSpaceKind_MetaCtrlEntity) + { + scoping_entity = rd_ctrl_entity_from_eval_space(lhs_interp.space); + } + + //- rjf: determine which type of child we're gathering + E_TypeKey lhs_type_key = lhs->type_key; + E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); + String8 name = rd_singular_from_code_name_plural(lhs_type->name); + CTRL_EntityKind entity_kind = CTRL_EntityKind_Null; + for EachNonZeroEnumVal(CTRL_EntityKind, k) + { + if(str8_match(name, ctrl_entity_kind_code_name_table[k], 0)) + { + entity_kind = k; + break; + } + } + + //- rjf: gather list of all entities which fit the bill + CTRL_EntityList list = {0}; + if(scoping_entity == &ctrl_entity_nil) + { + list = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, entity_kind); + } + else + { + for(CTRL_Entity *child = scoping_entity->first; child != &ctrl_entity_nil; child = child->next) + { + if(child->kind == entity_kind) + { + ctrl_entity_list_push(scratch.arena, &list, child); + } + } + } + + //- rjf: filter the list + CTRL_EntityList list__filtered = list; + if(filter.size != 0) + { + MemoryZeroStruct(&list__filtered); + for(CTRL_EntityNode *n = list.first; n != 0; n = n->next) + { + CTRL_Entity *entity = n->v; + DR_FStrList fstrs = rd_title_fstrs_from_ctrl_entity(scratch.arena, entity, 1); + String8 title_string = dr_string_from_fstrs(scratch.arena, &fstrs); + FuzzyMatchRangeList matches = fuzzy_match_find(scratch.arena, filter, title_string); + if(matches.count == matches.needle_part_count) + { + ctrl_entity_list_push(scratch.arena, &list__filtered, entity); + } + } + } + + //- rjf: list -> array & fill + CTRL_EntityArray *array = push_array(arena, CTRL_EntityArray, 1); + *array = ctrl_entity_array_from_list(arena, &list__filtered); + result.user_data = array; + result.idxed_expr_count = array->count; + } + scratch_end(scratch); + return result; +} + +E_LOOKUP_ACCESS_FUNCTION_DEF(ctrl_entities) +{ + Temp scratch = scratch_begin(&arena, 1); + E_LookupAccess result = {{&e_irnode_nil}}; + CTRL_Entity *entity = &ctrl_entity_nil; + if(kind == E_ExprKind_MemberAccess) + { + String8 rhs_name = rhs->string; + CTRL_Handle handle = ctrl_handle_from_string(rhs_name); + entity = ctrl_entity_from_handle(d_state->ctrl_entity_store, handle); + } + else if(kind == E_ExprKind_ArrayIndex) + { + E_IRTreeAndType rhs_irtree = e_irtree_and_type_from_expr(scratch.arena, rhs); + E_OpList rhs_oplist = e_oplist_from_irtree(scratch.arena, rhs_irtree.root); + String8 rhs_bytecode = e_bytecode_from_oplist(scratch.arena, &rhs_oplist); + E_Interpretation rhs_interp = e_interpret(rhs_bytecode); + E_Value rhs_value = rhs_interp.value; + U64 rhs_idx = rhs_value.u64; + CTRL_EntityArray *entities = (CTRL_EntityArray *)user_data; + if(0 <= rhs_idx && rhs_idx < entities->count) + { + entity = entities->v[rhs_idx]; + } + } + if(entity != &ctrl_entity_nil) + { + E_Space space = rd_eval_space_from_ctrl_entity(entity, RD_EvalSpaceKind_MetaCtrlEntity); + String8 name = ctrl_entity_kind_code_name_table[entity->kind]; + E_TypeKey type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, name); + result.irtree_and_type.root = e_irtree_set_space(arena, space, e_irtree_const_u(arena, 0)); + result.irtree_and_type.type_key = type_key; + result.irtree_and_type.mode = E_Mode_Offset; + } + scratch_end(scratch); + return result; +} + +E_LOOKUP_RANGE_FUNCTION_DEF(ctrl_entities) +{ + CTRL_EntityArray *entities = (CTRL_EntityArray *)user_data; + E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs); + Rng1U64 legal_range = r1u64(0, entities->count); + Rng1U64 read_range = intersect_1u64(legal_range, idx_range); + U64 read_count = dim_1u64(read_range); + for(U64 out_idx = 0; out_idx < read_count; out_idx += 1) + { + CTRL_Entity *entity = entities->v[out_idx + read_range.min]; + exprs[out_idx] = e_expr_irext_member_access(arena, lhs, &lhs_irtree, ctrl_string_from_handle(arena, entity->handle)); + } +} + +//////////////////////////////// +//~ rjf: Debug Info Tables Eval Hooks + +typedef struct RD_DebugInfoTableLookupAccel RD_DebugInfoTableLookupAccel; +struct RD_DebugInfoTableLookupAccel +{ + RDI_SectionKind section; + U64 rdis_count; + RDI_Parsed **rdis; + DI_SearchItemArray items; +}; + +E_LOOKUP_INFO_FUNCTION_DEF(debug_info_table) +{ + Temp scratch = scratch_begin(&arena, 1); + + // rjf: determine which debug info section we're dealing with + RDI_SectionKind section = RDI_SectionKind_NULL; + { + E_TypeKey lhs_type_key = lhs->type_key; + E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); + if(0){} + else if(str8_match(lhs_type->name, str8_lit("procedures"), 0)) {section = RDI_SectionKind_Procedures;} + else if(str8_match(lhs_type->name, str8_lit("globals"), 0)) {section = RDI_SectionKind_GlobalVariables;} + else if(str8_match(lhs_type->name, str8_lit("thread_locals"), 0)) {section = RDI_SectionKind_ThreadVariables;} + else if(str8_match(lhs_type->name, str8_lit("types"), 0)) {section = RDI_SectionKind_UDTs;} + } + + // rjf: gather debug info table items + RD_DebugInfoTableLookupAccel *accel = push_array(arena, RD_DebugInfoTableLookupAccel, 1); + if(section != RDI_SectionKind_NULL) + { + U64 endt_us = rd_state->frame_eval_memread_endt_us; + + //- rjf: unpack context + DI_KeyList dbgi_keys_list = d_push_active_dbgi_key_list(scratch.arena); + DI_KeyArray dbgi_keys = di_key_array_from_list(scratch.arena, &dbgi_keys_list); + U64 rdis_count = dbgi_keys.count; + RDI_Parsed **rdis = push_array(arena, RDI_Parsed *, rdis_count); + for(U64 idx = 0; idx < rdis_count; idx += 1) + { + rdis[idx] = di_rdi_from_key(rd_state->frame_di_scope, &dbgi_keys.v[idx], endt_us); + } + + //- rjf: query all filtered items from dbgi searching system + U128 fuzzy_search_key = {d_hash_from_string(str8_struct(&rd_regs()->view)), (U64)section}; + B32 items_stale = 0; + DI_SearchParams params = {section, dbgi_keys}; + accel->section = section; + accel->rdis_count = rdis_count; + accel->rdis = rdis; + accel->items = di_search_items_from_key_params_query(rd_state->frame_di_scope, fuzzy_search_key, ¶ms, filter, endt_us, &items_stale); + if(items_stale) + { + rd_request_frame(); + } + } + E_LookupInfo info = {accel, 0, accel->items.count}; + scratch_end(scratch); + return info; +} + +E_LOOKUP_RANGE_FUNCTION_DEF(debug_info_table) +{ + RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; + U64 needed_row_count = dim_1u64(idx_range); + for EachIndex(idx, needed_row_count) + { + // rjf: unpack row + DI_SearchItem *item = &accel->items.v[idx_range.min + idx]; + + // rjf: skip bad elements + if(item->dbgi_idx >= accel->rdis_count) + { + continue; + } + + // rjf: unpack row info + RDI_Parsed *rdi = accel->rdis[item->dbgi_idx]; + E_Module *module = &e_parse_state->ctx->modules[item->dbgi_idx]; + + // rjf: build expr + E_Expr *item_expr = &e_expr_nil; + { + U64 element_idx = item->idx; + switch(accel->section) + { + default:{}break; + case RDI_SectionKind_Procedures: + { + Temp scratch = scratch_begin(&arena, 1); + 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_ConstU64, e_value_u64(module->vaddr_range.min + 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_state->ctx->modules)); + String8 symbol_name = {0}; + symbol_name.str = rdi_string_from_idx(module->rdi, procedure->name_string_idx, &symbol_name.size); + String8List strings = {0}; + e_type_lhs_string_from_key(scratch.arena, type_key, &strings, 0, 0); + str8_list_push(scratch.arena, &strings, symbol_name); + e_type_rhs_string_from_key(scratch.arena, type_key, &strings, 0); + item_expr = e_push_expr(arena, E_ExprKind_LeafBytecode, 0); + item_expr->mode = E_Mode_Value; + item_expr->space = module->space; + item_expr->type_key = type_key; + item_expr->bytecode = bytecode; + item_expr->string = str8_list_join(arena, &strings, 0); + scratch_end(scratch); + }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_ConstU64, e_value_u64(module->vaddr_range.min + 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_state->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, e_value_u64(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_state->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_state->ctx->modules)); + item_expr = e_push_expr(arena, E_ExprKind_TypeIdent, 0); + item_expr->type_key = type_key; + }break; + } + } + + // rjf: fill + exprs[idx] = item_expr; + } +} + +E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(debug_info_table) +{ + RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; + U64 id = 0; + if(0 < num && num <= accel->items.count) + { + id = accel->items.v[num-1].idx+1; + } + return id; +} + +E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(debug_info_table) +{ + RD_DebugInfoTableLookupAccel *accel = (RD_DebugInfoTableLookupAccel *)user_data; + U64 num = di_search_item_num_from_array_element_idx__linear_search(&accel->items, id-1); + return num; +} +#endif diff --git a/src/raddbg/raddbg_eval.h b/src/raddbg/raddbg_eval.h new file mode 100644 index 00000000..d8c6af28 --- /dev/null +++ b/src/raddbg/raddbg_eval.h @@ -0,0 +1,88 @@ +// Copyright (c) 2024 Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#ifndef RADDBG_EVAL_H +#define RADDBG_EVAL_H + +//////////////////////////////// +//~ rjf: `commands` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(commands); +E_TYPE_ACCESS_FUNCTION_DEF(commands); +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(commands); + +//////////////////////////////// +//~ rjf: `watches` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(watches); +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(watches); +E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_DEF(watches); +E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(watches); + +//////////////////////////////// +//~ rjf: `locals` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(locals); +E_LOOKUP_RANGE_FUNCTION_DEF(locals); + +//////////////////////////////// +//~ rjf: `registers` Type Hooks + +E_LOOKUP_INFO_FUNCTION_DEF(registers); +E_LOOKUP_RANGE_FUNCTION_DEF(registers); + +//////////////////////////////// +//~ rjf: Schema Type Hooks + +#if 0 // TODO(rjf): @eval +E_TYPE_ACCESS_FUNCTION_DEF(schema); +E_TYPE_EXPAND_INFO_FUNCTION_DEF(schema); +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(schema); + +//////////////////////////////// +//~ rjf: Config Collection Type Hooks + +E_LOOKUP_INFO_FUNCTION_DEF(cfgs); +E_LOOKUP_ACCESS_FUNCTION_DEF(cfgs); +E_LOOKUP_RANGE_FUNCTION_DEF(cfgs); +E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(cfgs); +E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(cfgs); + +//////////////////////////////// +//~ rjf: `call_stack` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(call_stack); +E_TYPE_ACCESS_FUNCTION_DEF(call_stack); + +//////////////////////////////// +//~ rjf: `environment` Type Hooks + +E_TYPE_ACCESS_FUNCTION_DEF(environment); +E_TYPE_EXPAND_INFO_FUNCTION_DEF(environment); +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(environment); +E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(environment); +E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(environment); + +//////////////////////////////// +//~ rjf: `unattached_processes` Type Hooks + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(unattached_processes); +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(unattached_processes); + +//////////////////////////////// +//~ rjf: Control Entity List Type Hooks (`processes`, `threads`, etc.) + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(ctrl_entities); +E_LOOKUP_ACCESS_FUNCTION_DEF(ctrl_entities); +E_LOOKUP_RANGE_FUNCTION_DEF(ctrl_entities); + +//////////////////////////////// +//~ rjf: Debug Info Tables Eval Hooks + +E_LOOKUP_INFO_FUNCTION_DEF(debug_info_table); +E_LOOKUP_RANGE_FUNCTION_DEF(debug_info_table); +E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(debug_info_table); +E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(debug_info_table); +#endif + +#endif // RADDBG_EVAL_H diff --git a/src/raddbg/raddbg_inc.c b/src/raddbg/raddbg_inc.c index 07842d04..e3fef691 100644 --- a/src/raddbg/raddbg_inc.c +++ b/src/raddbg/raddbg_inc.c @@ -2,5 +2,6 @@ // Licensed under the MIT license (https://opensource.org/license/mit/) #include "raddbg_core.c" +#include "raddbg_eval.c" #include "raddbg_widgets.c" #include "raddbg_views.c" diff --git a/src/raddbg/raddbg_inc.h b/src/raddbg/raddbg_inc.h index 46cb0ece..2e131faf 100644 --- a/src/raddbg/raddbg_inc.h +++ b/src/raddbg/raddbg_inc.h @@ -5,6 +5,7 @@ #define RADDBG_INC_H #include "raddbg_core.h" +#include "raddbg_eval.h" #include "raddbg_widgets.h" #include "raddbg_views.h" diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 634fc015..b67927c5 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -943,37 +943,32 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) // rjf: unpack key & block EV_Block *block = row->block; EV_Key key = row->key; - E_IRTreeAndType parent_irtree = e_irtree_and_type_from_expr(scratch.arena, block->expr); - E_Type *parent_type = e_type_from_key__cached(parent_irtree.type_key); - E_Eval block_eval = e_eval_from_expr(scratch.arena, row->block->expr); + E_Eval block_eval = row->block->eval; E_TypeKey block_type_key = block_eval.irtree.type_key; E_TypeKind block_type_kind = e_type_kind_from_key(block_type_key); E_Type *block_type = e_type_from_key__cached(block_type_key); - // rjf: fill row's eval - info.eval = e_eval_from_expr(arena, row->expr); - // rjf: determine if row's expression is editable - if(block_type->flags & E_TypeFlag_EditableChildren || row->expr == &e_expr_nil) + if(block_type->flags & E_TypeFlag_EditableChildren || row->eval.expr == &e_expr_nil) { info.expr_is_editable = 1; } // rjf: determine row's module - CTRL_Entity *row_ctrl_entity = rd_ctrl_entity_from_eval_space(info.eval.space); + CTRL_Entity *row_ctrl_entity = rd_ctrl_entity_from_eval_space(row->eval.space); CTRL_Entity *row_module = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->module); - if(info.eval.space.kind == RD_EvalSpaceKind_CtrlEntity) + if(row->eval.space.kind == RD_EvalSpaceKind_CtrlEntity) { switch(row_ctrl_entity->kind) { default: case CTRL_EntityKind_Process: - if(info.eval.irtree.mode == E_Mode_Offset) + if(row->eval.irtree.mode == E_Mode_Offset) { - info.module = ctrl_module_from_process_vaddr(row_ctrl_entity, info.eval.value.u64); + info.module = ctrl_module_from_process_vaddr(row_ctrl_entity, row->eval.value.u64); }break; case CTRL_EntityKind_Thread: - if(info.eval.irtree.mode == E_Mode_Value) + if(row->eval.irtree.mode == E_Mode_Value) { CTRL_Entity *process = ctrl_process_from_entity(row_ctrl_entity); info.module = ctrl_module_from_process_vaddr(process, d_query_cached_rip_from_thread(row_ctrl_entity)); @@ -988,7 +983,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) if(entity->kind == CTRL_EntityKind_Thread) { info.callstack_thread = entity; - U64 frame_num = block->lookup_rule->num_from_id(key.child_id, block->lookup_rule_user_data); + U64 frame_num = ev_block_num_from_id(block, key.child_id); CTRL_Unwind unwind = d_query_cached_unwind_from_thread(entity); CTRL_CallStack call_stack = ctrl_call_stack_from_unwind(scratch.arena, di_scope, ctrl_process_from_entity(entity), &unwind); if(1 <= frame_num && frame_num <= call_stack.count) @@ -1005,7 +1000,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) if(block_type_kind == E_TypeKind_Set && (block_eval.space.kind == RD_EvalSpaceKind_MetaQuery || block_eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity)) { - info.group_entity = rd_ctrl_entity_from_eval_space(info.eval.space); + info.group_entity = rd_ctrl_entity_from_eval_space(row->eval.space); } // rjf: determine cfg group name / parent @@ -1037,8 +1032,8 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) } // rjf: determine cfgs/entities that this row is evaluating - RD_Cfg *evalled_cfg = rd_cfg_from_eval_space(info.eval.space); - CTRL_Entity *evalled_entity = (info.eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity ? rd_ctrl_entity_from_eval_space(info.eval.space) : &ctrl_entity_nil); + RD_Cfg *evalled_cfg = rd_cfg_from_eval_space(row->eval.space); + CTRL_Entity *evalled_entity = (row->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity ? rd_ctrl_entity_from_eval_space(row->eval.space) : &ctrl_entity_nil); // rjf: determine if this cfg/entity evaluation is top-level - e.g. if we // are evaluating a cfg tree, or some descendant of it @@ -1046,33 +1041,36 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) if(evalled_cfg != &rd_nil_cfg) { E_TypeKey top_level_type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, evalled_cfg->string); - is_top_level = (info.eval.value.u64 == 0 && e_type_key_match(top_level_type_key, info.eval.irtree.type_key)); + is_top_level = (row->eval.value.u64 == 0 && e_type_key_match(top_level_type_key, row->eval.irtree.type_key)); } if(evalled_entity != &ctrl_entity_nil) { String8 top_level_name = ctrl_entity_kind_code_name_table[evalled_entity->kind]; E_TypeKey top_level_type_key = e_string2typekey_map_lookup(rd_state->meta_name2type_map, top_level_name); - is_top_level = (info.eval.value.u64 == 0 && e_type_key_match(top_level_type_key, info.eval.irtree.type_key)); + is_top_level = (row->eval.value.u64 == 0 && e_type_key_match(top_level_type_key, row->eval.irtree.type_key)); } // rjf: determine view ui rule - info.view_ui_rule = rd_view_ui_rule_from_string(row->block->expand_rule->string); + // TODO(rjf): @eval + info.view_ui_rule = &rd_nil_view_ui_rule; // rd_view_ui_rule_from_string(row->block->expand_rule->string); +#if 0 // TODO(rjf): @eval if(info.view_ui_rule != &rd_nil_view_ui_rule) { info.view_ui_tag = row->block->expand_tag; } +#endif // rjf: fill row's cells { if(0){} // rjf: folder / file rows - else if(info.eval.space.kind == E_SpaceKind_FileSystem) + else if(row->eval.space.kind == E_SpaceKind_FileSystem) { - E_Type *type = e_type_from_key__cached(info.eval.irtree.type_key); + E_Type *type = e_type_from_key__cached(row->eval.irtree.type_key); if(type->kind == E_TypeKind_Set) { - String8 file_path = e_string_from_id(info.eval.value.u64); + String8 file_path = e_string_from_id(row->eval.value.u64); DR_FStrList fstrs = rd_title_fstrs_from_file_path(arena, file_path); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .flags = RD_WatchCellFlag_Button|RD_WatchCellFlag_IsNonCode, @@ -1098,13 +1096,13 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) } // rjf: singular button for unattached processes - else if(info.eval.space.kind == RD_EvalSpaceKind_MetaUnattachedProcess) + else if(row->eval.space.kind == RD_EvalSpaceKind_MetaUnattachedProcess) { - E_Type *type = e_type_from_key__cached(info.eval.irtree.type_key); + E_Type *type = e_type_from_key__cached(row->eval.irtree.type_key); if(str8_match(type->name, str8_lit("unattached_process"), 0)) { - U64 pid = info.eval.value.u128.u64[0]; - String8 name = e_string_from_id(info.eval.value.u128.u64[1]); + U64 pid = row->eval.value.u128.u64[0]; + String8 name = e_string_from_id(row->eval.value.u128.u64[1]); DR_FStrParams params = {rd_font_from_slot(RD_FontSlot_Main), rd_raster_flags_from_slot(RD_FontSlot_Main), ui_color_from_name(str8_lit("text")), ui_top_font_size()}; DR_FStrList fstrs = {0}; UI_TagF("weak") @@ -1217,22 +1215,22 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) } // rjf: singular row for queries - else if(info.eval.space.kind == RD_EvalSpaceKind_MetaQuery) + else if(row->eval.space.kind == RD_EvalSpaceKind_MetaQuery) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .pct = 1.f); } // rjf: singular button for commands - else if(info.eval.space.kind == RD_EvalSpaceKind_MetaCmd) + else if(row->eval.space.kind == RD_EvalSpaceKind_MetaCmd) { - E_Type *type = e_type_from_key__cached(info.eval.irtree.type_key); + E_Type *type = e_type_from_key__cached(row->eval.irtree.type_key); if(type->kind == E_TypeKind_Set) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .flags = 0, .pct = 1.f); } else { - String8 cmd_name = e_string_from_id(e_value_eval_from_eval(info.eval).value.u64); + String8 cmd_name = e_string_from_id(e_value_eval_from_eval(row->eval).value.u64); RD_CmdKindInfo *cmd_kind_info = rd_cmd_kind_info_from_string(cmd_name); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .flags = RD_WatchCellFlag_Button|RD_WatchCellFlag_ActivateWithSingleClick, .pct = 1.f, .fstrs = rd_title_fstrs_from_code_name(arena, cmd_kind_info->string)); } @@ -1245,28 +1243,28 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) } // rjf: for 'add-new' rows in meta-cfg evaluation spaces, only do expr - else if(info.eval.exprs.last == &e_expr_nil && info.group_cfg_name.size != 0 && info.group_cfg_child == &rd_nil_cfg) + else if(row->eval.expr == &e_expr_nil && info.group_cfg_name.size != 0 && info.group_cfg_child == &rd_nil_cfg) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .pct = 1.f); } // rjf: for meta-evaluation space booleans, only do expr - else if(e_type_kind_from_key(info.eval.irtree.type_key) == E_TypeKind_Bool && - (info.eval.space.kind == RD_EvalSpaceKind_MetaCfg || - info.eval.space.kind == RD_EvalSpaceKind_MetaCmd || - info.eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity)) + else if(e_type_kind_from_key(row->eval.irtree.type_key) == E_TypeKind_Bool && + (row->eval.space.kind == RD_EvalSpaceKind_MetaCfg || + row->eval.space.kind == RD_EvalSpaceKind_MetaCmd || + row->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity)) { rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .pct = 1.f); } // rjf: for meta-cfg evaluation spaces, only do expr/value - else if(info.eval.space.kind == RD_EvalSpaceKind_MetaCfg || - info.eval.space.kind == RD_EvalSpaceKind_MetaCmd || - info.eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity || - info.eval.space.kind == E_SpaceKind_File) + else if(row->eval.space.kind == RD_EvalSpaceKind_MetaCfg || + row->eval.space.kind == RD_EvalSpaceKind_MetaCmd || + row->eval.space.kind == RD_EvalSpaceKind_MetaCtrlEntity || + row->eval.space.kind == E_SpaceKind_File) { - if(e_type_kind_from_key(info.eval.irtree.type_key) == E_TypeKind_Array && - e_type_kind_from_key(e_type_direct_from_key(info.eval.irtree.type_key)) == E_TypeKind_U8) + if(e_type_kind_from_key(row->eval.irtree.type_key) == E_TypeKind_Array && + e_type_kind_from_key(e_type_direct_from_key(row->eval.irtree.type_key)) == E_TypeKind_U8) { info.can_expand = 0; } @@ -1371,11 +1369,11 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla { result.flags |= RD_WatchCellFlag_CanEdit; } - result.eval = (cell->eval.irtree.mode != E_Mode_Null ? cell->eval : e_eval_from_expr(arena, row->expr)); + result.eval = (cell->eval.irtree.mode != E_Mode_Null ? cell->eval : row->eval); result.string = row->string; if(result.string.size == 0) { - E_Expr *notable_expr = row->expr; + E_Expr *notable_expr = row->eval.expr; for(B32 good = 0; !good;) { switch(notable_expr->kind) @@ -1451,7 +1449,7 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla //- rjf: use cell's wrap string to wrap row's expression String8 wrap_string = cell->string; - E_Expr *root_expr = row->expr; + E_Expr *root_expr = row->eval.expr; if(wrap_string.size != 0) { E_Expr *wrap_expr = e_parse_expr_from_text(scratch.arena, wrap_string).exprs.last; @@ -1470,7 +1468,7 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla { if(t->expr->kind == E_ExprKind_LeafIdentifier && str8_match(t->expr->string, str8_lit("$expr"), 0)) { - E_Expr *original_expr_ref = e_expr_ref(scratch.arena, row->expr); + E_Expr *original_expr_ref = e_expr_ref(scratch.arena, row->eval.expr); if(t->parent != &e_expr_nil) { e_expr_insert_child(t->parent, t->expr, original_expr_ref); @@ -1526,7 +1524,7 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla //- rjf: view ui cells case RD_WatchCellKind_ViewUI: { - result.eval = (cell->eval.irtree.mode != E_Mode_Null ? cell->eval : e_eval_from_expr(arena, row->expr)); + result.eval = (cell->eval.irtree.mode != E_Mode_Null ? cell->eval : row->eval); result.view_ui_rule = row_info->view_ui_rule; result.view_ui_tag = row_info->view_ui_tag; }break; @@ -1948,7 +1946,7 @@ RD_VIEW_UI_FUNCTION_DEF(disasm) // B32 auto_selected = 0; E_Space auto_space = {0}; - if(eval.exprs.last == &e_expr_nil) + if(eval.expr == &e_expr_nil) { if(dv->temp_look_vaddr != 0 && dv->temp_look_run_gen == ctrl_run_gen()) { diff --git a/src/raddbg/raddbg_views.h b/src/raddbg/raddbg_views.h index c67e9ba3..a4961eda 100644 --- a/src/raddbg/raddbg_views.h +++ b/src/raddbg/raddbg_views.h @@ -88,7 +88,6 @@ struct RD_WatchCellList typedef struct RD_WatchRowInfo RD_WatchRowInfo; struct RD_WatchRowInfo { - E_Eval eval; CTRL_Entity *module; B32 can_expand; B32 expr_is_editable;