diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 5ede2ff9..49b61863 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -1565,6 +1565,8 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) //- rjf: call case E_ExprKind_Call: { + B32 start_disallow_chained_fastpaths = e_ir_state->disallow_chained_fastpaths; + e_ir_state->disallow_chained_fastpaths = 1; 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; @@ -1669,6 +1671,8 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) { e_msgf(arena, &result.msgs, E_MsgKind_InterpretationError, expr->location, "Calling this type is not supported."); } + + e_ir_state->disallow_chained_fastpaths = start_disallow_chained_fastpaths; }break; //- rjf: leaf bytecode @@ -2258,6 +2262,7 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr) } //- rjf: check chained expressions for simple wrappers + if(!e_ir_state->disallow_chained_fastpaths) { struct { diff --git a/src/eval/eval_ir.h b/src/eval/eval_ir.h index 67b8f51a..60c0226b 100644 --- a/src/eval/eval_ir.h +++ b/src/eval/eval_ir.h @@ -155,6 +155,7 @@ struct E_IRState // rjf: overridden irtree E_IRTreeAndType *overridden_irtree; B32 disallow_autohooks; + B32 disallow_chained_fastpaths; // rjf: caches E_UsedExprMap *used_expr_map; diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index 44d8c57a..d25fb04c 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -1402,6 +1402,30 @@ e_type_data_members_from_key(Arena *arena, E_TypeKey key) return members; } +internal E_TypeExpandRule * +e_expand_rule_from_type_key(E_TypeKey key) +{ + E_TypeExpandRule *rule = &e_type_expand_rule__default; + { + E_Type *type = e_type_from_key__cached(key); + if(type->expand.info != 0) + { + rule = &type->expand; + } + for(E_Type *lens_type = type; + lens_type->kind == E_TypeKind_Lens || lens_type->kind == E_TypeKind_Set; + lens_type = e_type_from_key__cached(lens_type->direct_type_key)) + { + if(lens_type->expand.info != 0) + { + rule = &lens_type->expand; + break; + } + } + } + return rule; +} + //- rjf: type key traversal internal E_TypeKey @@ -2281,6 +2305,104 @@ E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_DEF(identity) return id; } +//////////////////////////////// +//~ rjf: (Built-In Type Hooks) `only` lens + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(only) +{ + E_Type *type = e_type_from_key__cached(irtree->type_key); + E_TypeExpandInfo info = {0, type->count}; + return info; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(only) +{ + E_Type *type = e_type_from_key__cached(irtree->type_key); + U64 out_idx = 0; + for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) + { + E_Expr *arg = type->args[idx]; + if(arg->string.size != 0) + { + exprs_out[out_idx] = e_expr_irext_member_access(arena, expr, irtree, arg->string); + } + } +} + +//////////////////////////////// +//~ rjf: (Built-In Type Hooks) `omit` lens + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(omit) +{ + E_Type *type = e_type_from_key__cached(irtree->type_key); + String8Array allowed_children_array = {0}; + { + Temp scratch = scratch_begin(&arena, 1); + String8List allowed_children = {0}; + { + E_Type *stripped_type = e_type_from_key__cached(type->direct_type_key); + // TODO(rjf): this is kind of ugly due to the need to call irext, + // i wish it was possible to have an easier way to "strip" the current + // lens & evaluate the wrapped expression? + E_IRTreeAndType irtree_stripped = *irtree; + irtree_stripped.type_key = type->direct_type_key; + irtree_stripped.user_data = stripped_type->irext ? stripped_type->irext(scratch.arena, expr, &irtree_stripped).user_data : 0; + E_TypeExpandRule *expand_rule = e_expand_rule_from_type_key(irtree_stripped.type_key); + E_TypeExpandInfo expand_info = expand_rule->info(scratch.arena, expr, &irtree_stripped, filter); + if(expand_info.expr_count < 4096) + { + E_Expr **exprs = push_array(scratch.arena, E_Expr *, expand_info.expr_count); + String8 *exprs_strings = push_array(scratch.arena, String8, expand_info.expr_count); + for EachIndex(idx, expand_info.expr_count) + { + exprs[idx] = &e_expr_nil; + } + expand_rule->range(scratch.arena, expand_info.user_data, expr, &irtree_stripped, filter, r1u64(0, expand_info.expr_count), exprs, exprs_strings); + for EachIndex(idx, expand_info.expr_count) + { + if(exprs[idx]->kind == E_ExprKind_MemberAccess) + { + String8 name = exprs[idx]->first->next->string; + B32 name_is_allowed = 1; + for EachIndex(arg_idx, type->count) + { + if(str8_match(type->args[arg_idx]->string, name, 0)) + { + name_is_allowed = 0; + break; + } + } + if(name_is_allowed) + { + str8_list_push(scratch.arena, &allowed_children, push_str8_copy(arena, name)); + } + } + } + } + } + allowed_children_array = str8_array_from_list(arena, &allowed_children); + scratch_end(scratch); + } + String8Array *ext = push_array(arena, String8Array, 1); + *ext = allowed_children_array; + E_TypeExpandInfo info = {ext, ext->count}; + return info; +} + +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(omit) +{ + String8Array *ext = (String8Array *)user_data; + U64 out_idx = 0; + for(U64 idx = idx_range.min; idx < idx_range.max; idx += 1, out_idx += 1) + { + String8 name = ext->v[idx]; + if(name.size != 0) + { + exprs_out[out_idx] = e_expr_irext_member_access(arena, expr, irtree, name); + } + } +} + //////////////////////////////// //~ rjf: (Built-In Type Hooks) `sequence` lens diff --git a/src/eval/eval_types.h b/src/eval/eval_types.h index ae1c3dd5..20636b29 100644 --- a/src/eval/eval_types.h +++ b/src/eval/eval_types.h @@ -268,6 +268,7 @@ internal U64 e_type_byte_size_from_key(E_TypeKey key); internal E_Type *e_type_from_key(Arena *arena, E_TypeKey key); internal int e_type_qsort_compare_members_offset(E_Member *a, E_Member *b); internal E_MemberArray e_type_data_members_from_key(Arena *arena, E_TypeKey key); +internal E_TypeExpandRule *e_expand_rule_from_type_key(E_TypeKey key); //- rjf: type key traversal internal E_TypeKey e_type_key_direct(E_TypeKey key); @@ -309,6 +310,12 @@ 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); +//////////////////////////////// +//~ rjf: (Built-In Type Hooks) `only` lens + +E_TYPE_EXPAND_INFO_FUNCTION_DEF(only); +E_TYPE_EXPAND_RANGE_FUNCTION_DEF(only); + //////////////////////////////// //~ rjf: (Built-In Type Hooks) `sequence` lens diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index e4ae439a..61526059 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -84,7 +84,7 @@ ev_type_key_and_mode_is_expandable(E_TypeKey type_key, E_Mode mode) { B32 result = 0; { - if(e_type_kind_from_key(type_key) == E_TypeKind_Lens) + if(!result && e_type_kind_from_key(type_key) == E_TypeKind_Lens) { for(E_Type *lens_type = e_type_from_key__cached(type_key); lens_type->kind == E_TypeKind_Lens; @@ -97,7 +97,7 @@ ev_type_key_and_mode_is_expandable(E_TypeKey type_key, E_Mode mode) } } } - else + if(!result) { E_TypeKey expand_type_key = e_default_expansion_type_from_key(type_key); E_TypeKind expand_type_kind = e_type_kind_from_key(expand_type_key); @@ -574,24 +574,9 @@ ev_block_tree_from_expr(Arena *arena, EV_View *view, String8 filter, E_Expr *exp // 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; - } - for(E_Type *lens_type = type; - lens_type->kind == E_TypeKind_Lens || lens_type->kind == E_TypeKind_Set; - lens_type = e_type_from_key__cached(lens_type->direct_type_key)) - { - if(lens_type->expand.info != 0) - { - type_expand_rule = &lens_type->expand; - break; - } - } - // rjf: get eval's visualization expansion rule + // rjf: get expansion rules from type + E_TypeExpandRule *type_expand_rule = e_expand_rule_from_type_key(type_key); EV_ExpandRule *viz_expand_rule = ev_expand_rule_from_type_key(type_key); // rjf: skip if no expansion rule, & type info disallows expansion @@ -2094,11 +2079,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string) { expand_data = it->top_task->user_data = push_array(arena, EV_ExpandedTypeData, 1); expand_data->type = e_type_from_key__cached(type_key); - expand_data->expand_rule = &e_type_expand_rule__default; - if(expand_data->type->expand.info != 0) - { - expand_data->expand_rule = &expand_data->type->expand; - } + expand_data->expand_rule = e_expand_rule_from_type_key(type_key); expand_data->expand_info = expand_data->expand_rule->info(arena, eval.expr, &eval.irtree, params->filter); } switch(task_idx) diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index ca291bd4..2d3fed09 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -12366,6 +12366,8 @@ rd_frame(void) {str8_lit("no_string"), 1, 1, 0, 0, 0, {0}}, {str8_lit("no_addr"), 1, 1, 0, 0, 0, {0}}, {str8_lit("sequence"), 0, 0, 1, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(sequence), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(sequence)}}, + {str8_lit("only"), 0, 0, 0, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(only), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(only)}}, + {str8_lit("omit"), 0, 0, 0, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(omit), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(omit)}}, {str8_lit("range1"), 0, 0, 0, 0, 0, {0}}, {str8_lit("array"), 0, 0, 1, 0, 0, {E_TYPE_EXPAND_INFO_FUNCTION_NAME(array), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(array)}}, {str8_lit("slice"), 0, 0, 1, E_TYPE_IREXT_FUNCTION_NAME(slice), E_TYPE_ACCESS_FUNCTION_NAME(slice), {E_TYPE_EXPAND_INFO_FUNCTION_NAME(slice), E_TYPE_EXPAND_RANGE_FUNCTION_NAME(slice)}}, diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index d6fd181d..4c4ef5ff 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -1079,7 +1079,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) if(0){} // rjf: table rows - else if(maybe_table_type->kind == E_TypeKind_Lens && str8_match(maybe_table_type->name, str8_lit("table"), 0) && maybe_table_type->count >= 1) + else if(block->parent != &ev_nil_block && maybe_table_type->kind == E_TypeKind_Lens && str8_match(maybe_table_type->name, str8_lit("table"), 0) && maybe_table_type->count >= 1) { U64 column_count = maybe_table_type->count; info.cell_style_key = push_str8f(arena, "table_%I64u_cols", column_count); @@ -1371,7 +1371,7 @@ rd_watch_row_info_from_row(Arena *arena, EV_Row *row) #define take_pct() (next_pct = (F32)f64_from_str8(w_cfg->string), w_cfg = w_cfg->next, next_pct) rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Expr, .default_pct = 0.35f, .pct = take_pct()); rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .default_pct = 0.40f, .pct = take_pct()); - rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("typeof($expr)"), .default_pct = 0.25f, .pct = take_pct()); + rd_watch_cell_list_push_new(arena, &info.cells, RD_WatchCellKind_Eval, .string = str8_lit("typeof(raw($expr))"), .default_pct = 0.25f, .pct = take_pct()); #undef take_pct } }