diff --git a/src/eval/eval_core.c b/src/eval/eval_core.c index c9d9ddb6..b1759155 100644 --- a/src/eval/eval_core.c +++ b/src/eval/eval_core.c @@ -160,6 +160,17 @@ e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push) MemoryZeroStruct(to_push); } +internal E_MsgList +e_msg_list_copy(Arena *arena, E_MsgList *src) +{ + E_MsgList dst = {0}; + for(E_Msg *msg = src->first; msg != 0; msg = msg->next) + { + e_msg(arena, &dst, msg->kind, msg->location, msg->text); + } + return dst; +} + //////////////////////////////// //~ rjf: Space Functions @@ -796,6 +807,8 @@ e_parse_from_bundle(E_CacheBundle *bundle) { bundle->flags |= E_CacheBundleFlag_Parse; bundle->parse = e_push_parse_from_string(e_cache->arena, bundle->string); + E_MsgList msgs_copy = e_msg_list_copy(e_cache->arena, &bundle->parse.msgs); + e_msg_list_concat_in_place(&bundle->msgs, &msgs_copy); } E_Parse parse = bundle->parse; return parse; @@ -810,6 +823,8 @@ e_irtree_from_bundle(E_CacheBundle *bundle) E_IRTreeAndType overridden = e_irtree_from_key(bundle->parent_key); E_Parse parse = e_parse_from_bundle(bundle); bundle->irtree = e_push_irtree_and_type_from_expr(e_cache->arena, &overridden, 0, 0, parse.expr); + E_MsgList msgs_copy = e_msg_list_copy(e_cache->arena, &bundle->irtree.msgs); + e_msg_list_concat_in_place(&bundle->msgs, &msgs_copy); } E_IRTreeAndType result = bundle->irtree; return result; @@ -839,6 +854,10 @@ e_interpretation_from_bundle(E_CacheBundle *bundle) bundle->flags |= E_CacheBundleFlag_Interpret; String8 bytecode = e_bytecode_from_bundle(bundle); E_Interpretation interpret = e_interpret(bytecode); + if(E_InterpretationCode_Good < interpret.code && interpret.code < E_InterpretationCode_COUNT) + { + e_msg(e_cache->arena, &bundle->msgs, E_MsgKind_InterpretationError, 0, e_interpretation_code_display_strings[interpret.code]); + } bundle->interpretation = interpret; } E_Interpretation interpret = bundle->interpretation; @@ -857,6 +876,7 @@ e_eval_from_bundle(E_CacheBundle *bundle) .expr = e_parse_from_bundle(bundle).expr, .irtree = e_irtree_from_bundle(bundle), .bytecode = e_bytecode_from_bundle(bundle), + .msgs = bundle->msgs, }; E_Interpretation interpretation = e_interpretation_from_bundle(bundle); eval.code = interpretation.code; diff --git a/src/eval/eval_core.h b/src/eval/eval_core.h index b56d64be..5159b1c6 100644 --- a/src/eval/eval_core.h +++ b/src/eval/eval_core.h @@ -887,6 +887,7 @@ struct E_CacheBundle E_IRTreeAndType irtree; String8 bytecode; E_Interpretation interpretation; + E_MsgList msgs; }; typedef struct E_CacheNode E_CacheNode; @@ -1026,6 +1027,7 @@ internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src); internal void e_msg(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, String8 text); internal void e_msgf(Arena *arena, E_MsgList *msgs, E_MsgKind kind, void *location, char *fmt, ...); internal void e_msg_list_concat_in_place(E_MsgList *dst, E_MsgList *to_push); +internal E_MsgList e_msg_list_copy(Arena *arena, E_MsgList *src); //////////////////////////////// //~ rjf: Space Functions diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index ce077dc8..52eda47a 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -493,14 +493,13 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) E_Expr *exprr = exprl->next; E_IRTreeAndType l = *lhs_irtree; E_IRTreeAndType r = e_push_irtree_and_type_from_expr(arena, overridden, 0, 0, exprr); + e_msg_list_concat_in_place(&result.msgs, &r.msgs); E_TypeKey l_restype = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKey r_restype = e_type_key_unwrap(r.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind l_restype_kind = e_type_kind_from_key(l_restype); E_TypeKind r_restype_kind = e_type_kind_from_key(r_restype); E_TypeKey direct_type = e_type_key_unwrap(l_restype, E_TypeUnwrapFlag_All); U64 direct_type_size = e_type_byte_size_from_key(direct_type); - e_msg_list_concat_in_place(&result.msgs, &l.msgs); - e_msg_list_concat_in_place(&result.msgs, &r.msgs); // rjf: bad conditions? -> error if applicable, exit if(r.root->op == 0) @@ -586,7 +585,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default) //- rjf: top-level irtree/type extraction internal E_IRTreeAndType -e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr) +e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_overridden, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr) { ProfBeginFunction(); Temp scratch = scratch_begin(&arena, 1); @@ -603,7 +602,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 E_Expr *expr; E_IRTreeAndType *prev; }; - Task start_task = {0, root_expr, overridden}; + Task start_task = {0, root_expr, root_overridden}; Task *first_task = &start_task; Task *last_task = first_task; for(Task *t = first_task; t != 0; t = t->next) @@ -614,9 +613,11 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 e_expr_poison(expr); //- rjf: select the task's previous ir-tree-and-type as the overridden tree + E_IRTreeAndType *overridden = 0; if(t->prev != 0) { - overridden = t->prev; + overridden = push_array(arena, E_IRTreeAndType, 1); + MemoryCopyStruct(overridden, t->prev); } //- rjf: do expr -> irtree generation for this expression @@ -636,6 +637,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 // rjf: unpack left-hand-side E_Expr *lhs = expr->first; E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, lhs); + e_msg_list_concat_in_place(&result.msgs, &lhs_irtree.msgs); // rjf: try all IR trees in chain for(E_IRTreeAndType *lhs_irtree_try = &lhs_irtree; lhs_irtree_try != 0; lhs_irtree_try = lhs_irtree_try->prev) @@ -692,11 +694,11 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); E_TypeKind r_type_kind = e_type_kind_from_key(r_type); E_TypeKey r_type_direct = e_type_key_unwrap(r_type, E_TypeUnwrapFlag_All); 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) @@ -751,10 +753,10 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = r_tree.type_key; E_TypeKey r_type_unwrapped = e_type_key_unwrap(r_type, E_TypeUnwrapFlag_AllDecorative); 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) @@ -779,6 +781,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 E_Expr *cast_type_expr = expr->first; E_Expr *casted_expr = cast_type_expr->next; E_IRTreeAndType cast_irtree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, cast_type_expr); + e_msg_list_concat_in_place(&result.msgs, &cast_irtree.msgs); E_TypeKey cast_type = cast_irtree.type_key; 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); @@ -915,12 +918,12 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); 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_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) @@ -948,12 +951,12 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 // rjf: unpack operand E_Expr *r_expr = expr->first; E_IRTreeAndType r_tree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, r_expr); + e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs); E_TypeKey r_type = e_type_key_unwrap(r_tree.type_key, E_TypeUnwrapFlag_AllDecorative); 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) @@ -1273,6 +1276,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 { E_Expr *lhs = expr->first; E_IRTreeAndType lhs_irtree = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, 1, lhs); + e_msg_list_concat_in_place(&result.msgs, &lhs_irtree.msgs); E_TypeKey lhs_type_key = lhs_irtree.type_key; E_Type *lhs_type = e_type_from_key__cached(lhs_type_key); @@ -1294,19 +1298,30 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 e_expr_push_child(call, e_expr_ref(arena, arg)); } result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, call); + E_MsgList new_msgs = {0}; + e_msg_list_concat_in_place(&new_msgs, &lhs_irtree.msgs); + e_msg_list_concat_in_place(&new_msgs, &result.msgs); + result.msgs = new_msgs; // rjf: is "raw"? -> try to return overridden tree, otherwise strip all // lens types from result; disallow auto-hooks if(str8_match(callee->string, str8_lit("raw"), 0)) { disallow_autohooks = 1; - if(overridden != 0) + if(overridden->root != &e_irnode_nil) { - result = *overridden; - for(E_IRTreeAndType *prev = overridden->prev; prev != 0; prev = prev->prev) + E_MsgList existing_msgs = result.msgs; + for(E_IRTreeAndType *prev = overridden; prev->root != &e_irnode_nil; prev = prev->prev) { result = *prev; + if(e_type_kind_from_key(prev->type_key) != E_TypeKind_Lens) + { + break; + } } + E_MsgList overridden_msgs = e_msg_list_copy(arena, &result.msgs); + result.msgs = existing_msgs; + e_msg_list_concat_in_place(&result.msgs, &overridden_msgs); } else { @@ -1322,7 +1337,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 Temp scratch = scratch_begin(&arena, 1); // rjf: generate result via first argument to lens - result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, lhs->next); + result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, 1, lhs->next); // rjf: count extra arguments U64 arg_count = 0; @@ -1346,17 +1361,25 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 if(str8_match(lhs_type->name, str8_lit("raw"), 0)) { disallow_autohooks = 1; - if(overridden != 0) + if(overridden->root != &e_irnode_nil) { + E_MsgList existing_msgs = result.msgs; result = *overridden; - for(E_IRTreeAndType *prev = overridden->prev; prev != 0; prev = prev->prev) + for(E_IRTreeAndType *prev = overridden; prev->root != &e_irnode_nil; prev = prev->prev) { result = *prev; + if(e_type_kind_from_key(prev->type_key) != E_TypeKind_Lens) + { + break; + } } + E_MsgList overridden_msgs = e_msg_list_copy(arena, &result.msgs); + result.msgs = existing_msgs; + e_msg_list_concat_in_place(&result.msgs, &overridden_msgs); } else { - result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, disallow_chained_fastpaths, lhs->next); + result = e_push_irtree_and_type_from_expr(arena, overridden, disallow_autohooks, 1, lhs->next); result.type_key = e_type_key_unwrap(result.type_key, E_TypeUnwrapFlag_Lenses); } } @@ -1484,7 +1507,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 } //- rjf: try to map name as overridden expression signifier ('$') - if(!string_mapped && str8_match(string, str8_lit("$"), 0) && overridden != 0) + if(!string_mapped && str8_match(string, str8_lit("$"), 0) && (overridden->root != &e_irnode_nil || overridden->msgs.first != 0)) { E_OpList oplist = e_oplist_from_irtree(arena, overridden->root); string_mapped = 1; @@ -1492,11 +1515,14 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 mapped_bytecode_mode = overridden->mode; mapped_type_key = overridden->type_key; disallow_autohooks = 1; + E_MsgList msgs = e_msg_list_copy(arena, &overridden->msgs); + e_msg_list_concat_in_place(&result.msgs, &msgs); } //- rjf: try to map name as implicit access of overridden expression ('$.member_name', where the $. prefix is omitted) - if(!string_mapped && overridden != 0) + if(!string_mapped && overridden->root != &e_irnode_nil) { + // TODO(rjf): @eval E_Expr *access = e_expr_irext_member_access(scratch.arena, &e_expr_nil, overridden, string); E_IRTreeAndType access_irtree = e_push_irtree_and_type_from_expr(scratch.arena, overridden, disallow_autohooks, disallow_chained_fastpaths, access); if(access_irtree.root != &e_irnode_nil) @@ -1506,6 +1532,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 mapped_type_key = access_irtree.type_key; mapped_bytecode = e_bytecode_from_oplist(arena, &oplist); mapped_bytecode_mode = access_irtree.mode; + e_msg_list_concat_in_place(&result.msgs, &access_irtree.msgs); } } @@ -1884,7 +1911,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 } //- rjf: error on failure-to-generate - if(!generated) + if(!generated && !str8_match(string, str8_lit("$"), 0)) { e_msgf(arena, &result.msgs, E_MsgKind_ResolutionFailure, expr->location, "`%S` could not be found.", string); } @@ -2066,8 +2093,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 //- rjf: equip previous task's irtree if(t->prev != 0) { - result.prev = push_array(arena, E_IRTreeAndType, 1); - result.prev[0] = *t->prev; + result.prev = overridden; } //- rjf: find any auto hooks according to this generation's type @@ -2084,8 +2110,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 Task *task = push_array(scratch.arena, Task, 1); SLLQueuePush(first_task, last_task, task); task->expr = e; - task->prev = push_array(scratch.arena, E_IRTreeAndType, 1); - task->prev[0] = result; + task->prev = &result; break; } } diff --git a/src/eval/eval_ir.h b/src/eval/eval_ir.h index 2bc467dd..c98a70fa 100644 --- a/src/eval/eval_ir.h +++ b/src/eval/eval_ir.h @@ -88,7 +88,7 @@ internal void e_expr_unpoison(E_Expr *expr); //- rjf: top-level irtree/type extraction E_TYPE_ACCESS_FUNCTION_DEF(default); -internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *overridden, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr); +internal E_IRTreeAndType e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_overridden, B32 disallow_autohooks, B32 disallow_chained_fastpaths, E_Expr *root_expr); //- rjf: irtree -> linear ops/bytecode internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out); diff --git a/src/eval/eval_types.c b/src/eval/eval_types.c index 5b4d4d97..8f4fe480 100644 --- a/src/eval/eval_types.c +++ b/src/eval/eval_types.c @@ -1367,7 +1367,7 @@ e_type_data_members_from_key(Arena *arena, E_TypeKey key) padding_member->kind = E_MemberKind_Padding; padding_member->type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), n->size, E_TypeFlag_IsNotText); padding_member->off = n->off; - padding_member->name = push_str8f(arena, "[padding %I64u]", padding_idx); + padding_member->name = push_str8f(arena, "$padding_%I64u", padding_idx); padding_idx += 1; } members = new_members; @@ -2355,13 +2355,21 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(array) U64 read_range_count = dim_1u64(idx_range); for(U64 idx = 0; idx < read_range_count; idx += 1) { - evals_out[idx] = e_eval_wrapf(eval, "$[I64u]", idx_range.min + idx); + evals_out[idx] = e_eval_wrapf(eval, "$[%I64u]", idx_range.min + idx); } } //////////////////////////////// //~ rjf: (Built-In Type Hooks) `slice` lens +typedef struct E_SliceIRExt E_SliceIRExt; +struct E_SliceIRExt +{ + E_Member *base_ptr_member; + E_Member *opl_ptr_member; + E_Member *count_member; +}; + typedef struct E_SliceAccel E_SliceAccel; struct E_SliceAccel { @@ -2373,7 +2381,7 @@ struct E_SliceAccel E_TYPE_IREXT_FUNCTION_DEF(slice) { - E_SliceAccel *accel = push_array(arena, E_SliceAccel, 1); + E_SliceIRExt *ext = push_array(arena, E_SliceIRExt, 1); { Temp scratch = scratch_begin(&arena, 1); @@ -2416,77 +2424,21 @@ E_TYPE_IREXT_FUNCTION_DEF(slice) } } - // rjf: determine architecture - Arch arch = e_base_ctx->primary_module->arch; - if(base_ptr_member != 0) - { - E_Type *type = e_type_from_key__cached(base_ptr_member->type_key); - arch = type->arch; - } - - // rjf: evaluate count member, determine count - U64 count = 0; - if(count_member != 0) - { - E_Expr *count_member_expr = e_expr_irext_member_access(arena, expr, irtree, count_member->name); - E_Value count_member_value = e_value_from_expr(count_member_expr); - count = count_member_value.u64; - } - - // rjf: evaluate base ptr member, determine base address - U64 base_ptr_vaddr = 0; - if(base_ptr_member != 0) - { - E_Expr *base_ptr_member_expr = e_expr_irext_member_access(arena, expr, irtree, base_ptr_member->name); - E_Value base_ptr_member_value = e_value_from_expr(base_ptr_member_expr); - base_ptr_vaddr = base_ptr_member_value.u64; - } - - // rjf: evaluate opl ptr member, determine opl address - U64 opl_ptr_vaddr = 0; - if(count_member == 0 && opl_ptr_member != 0) - { - E_Expr *opl_ptr_member_expr = e_expr_irext_member_access(arena, expr, irtree, opl_ptr_member->name); - E_Value opl_ptr_member_value = e_value_from_expr(opl_ptr_member_expr); - opl_ptr_vaddr = opl_ptr_member_value.u64; - } - - // rjf: determine element type - E_TypeKey element_type_key = zero_struct; - if(base_ptr_member != 0) - { - element_type_key = e_type_key_direct(base_ptr_member->type_key); - } - - // rjf: if no count, but base/opl, swap base/opl if needed, and measure count - if(count_member == 0 && opl_ptr_member != 0 && base_ptr_member != 0) - { - U64 min_vaddr = Min(base_ptr_vaddr, opl_ptr_vaddr); - U64 max_vaddr = Max(base_ptr_vaddr, opl_ptr_vaddr); - base_ptr_vaddr = min_vaddr; - opl_ptr_vaddr = max_vaddr; - count = (opl_ptr_vaddr - base_ptr_vaddr) / e_type_byte_size_from_key(element_type_key); - } - - // rjf: fill - if((count_member || opl_ptr_member) && base_ptr_member) - { - accel->arch = arch; - accel->count = count; - accel->base_ptr_vaddr = base_ptr_vaddr; - accel->element_type_key = element_type_key; - } + // rjf: fill extension + ext->base_ptr_member = base_ptr_member; + ext->opl_ptr_member = opl_ptr_member; + ext->count_member = count_member; } scratch_end(scratch); } - E_IRExt result = {accel}; + E_IRExt result = {ext}; return result; } E_TYPE_ACCESS_FUNCTION_DEF(slice) { E_IRTreeAndType result = {&e_irnode_nil}; - E_SliceAccel *accel = (E_SliceAccel *)lhs_irtree->user_data; + E_SliceIRExt *ext = (E_SliceIRExt *)lhs_irtree->user_data; switch(expr->kind) { default: @@ -2495,18 +2447,37 @@ E_TYPE_ACCESS_FUNCTION_DEF(slice) result = E_TYPE_ACCESS_FUNCTION_NAME(default)(arena, overridden, expr, lhs_irtree); }break; case E_ExprKind_ArrayIndex: + if(ext->base_ptr_member != 0) { - E_Value rhs_value = e_value_from_expr(expr->first->next); - U64 rhs_idx = rhs_value.u64; - if(0 <= rhs_idx && rhs_idx < accel->count) + Temp scratch = scratch_begin(&arena, 1); + + // rjf: compute bytecode of struct + E_OpList lhs_oplist = e_oplist_from_irtree(scratch.arena, lhs_irtree->root); + String8 lhs_bytecode = e_bytecode_from_oplist(arena, &lhs_oplist); + + // rjf: build expression tree to access base pointer's member, then do an index + E_Expr *idx_expr = e_push_expr(scratch.arena, E_ExprKind_ArrayIndex, 0); + E_Expr *dot_expr = e_push_expr(scratch.arena, E_ExprKind_MemberAccess, 0); + E_Expr *lhs_expr = e_push_expr(scratch.arena, E_ExprKind_LeafBytecode, 0); + E_Expr *base_ptr_expr = e_push_expr(scratch.arena, E_ExprKind_LeafIdentifier, 0); + e_expr_push_child(dot_expr, lhs_expr); + e_expr_push_child(dot_expr, base_ptr_expr); + e_expr_push_child(idx_expr, dot_expr); + e_expr_push_child(idx_expr, e_expr_ref(scratch.arena, expr->first->next)); { - E_Type *element_type = e_type_from_key__cached(accel->element_type_key); - U64 offset = element_type->byte_size*rhs_idx; - U64 vaddr = accel->base_ptr_vaddr + offset; - result.root = e_irtree_const_u(arena, vaddr); - result.type_key = accel->element_type_key; - result.mode = E_Mode_Offset; + lhs_expr->mode = lhs_irtree->mode; + lhs_expr->bytecode = lhs_bytecode; + lhs_expr->type_key = e_type_key_unwrap(lhs_irtree->type_key, E_TypeUnwrapFlag_Lenses); } + { + base_ptr_expr->string = ext->base_ptr_member->name; + } + + // rjf: compute struct.base_ptr IR tree + E_IRTreeAndType override = {&e_irnode_nil}; + result = e_push_irtree_and_type_from_expr(arena, &override, 0, 0, idx_expr); + + scratch_end(scratch); }break; } return result; @@ -2514,8 +2485,19 @@ E_TYPE_ACCESS_FUNCTION_DEF(slice) E_TYPE_EXPAND_INFO_FUNCTION_DEF(slice) { - E_SliceAccel *accel = (E_SliceAccel *)eval.irtree.user_data; - E_TypeExpandInfo info = {accel, accel->count}; + E_SliceIRExt *accel = (E_SliceIRExt *)eval.irtree.user_data; + U64 count = 0; + { + if(accel->count_member != 0) + { + count = e_value_eval_from_eval(e_eval_wrapf(eval, "$.%S", accel->count_member->name)).value.u64; + } + else if(accel->opl_ptr_member != 0 && accel->base_ptr_member != 0) + { + count = e_value_eval_from_eval(e_eval_wrapf(eval, "$.%S - $.%S", accel->opl_ptr_member->name, accel->base_ptr_member->name)).value.u64; + } + } + E_TypeExpandInfo info = {0, count}; return info; } @@ -2611,7 +2593,7 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(folder) { 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); - path_expr_string = push_str8f(arena, "file:\"%S\"", escaped_from_raw_str8(scratch.arena, folder_path)); + path_expr_string = push_str8f(arena, "folder:\"%S/\"", escaped_from_raw_str8(scratch.arena, folder_path)); } else if(accel->folders.count <= idx && idx < accel->folders.count + accel->files.count) { diff --git a/src/eval_visualization/eval_visualization_core.c b/src/eval_visualization/eval_visualization_core.c index 422ff1ec..086b1605 100644 --- a/src/eval_visualization/eval_visualization_core.c +++ b/src/eval_visualization/eval_visualization_core.c @@ -542,12 +542,13 @@ ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval eval Task *next; EV_Block *parent_block; E_Eval eval; + E_Expr *next_expr; U64 child_id; U64 split_relative_idx; B32 default_expanded; B32 force_expanded; }; - Task start_task = {0, tree.root, tree.root->eval, 1, 0}; + Task start_task = {0, tree.root, tree.root->eval, tree.root->eval.expr->next, 1, 0}; Task *first_task = &start_task; Task *last_task = first_task; @@ -708,6 +709,7 @@ ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval eval SLLQueuePush(first_task, last_task, task); task->parent_block = expansion_block; task->eval = child_eval; + task->next_expr = &e_expr_nil; task->child_id = child_key.child_id; task->split_relative_idx = split_relative_idx; task->default_expanded = viz_expand_info.rows_default_expanded; @@ -715,13 +717,14 @@ ev_block_tree_from_eval(Arena *arena, EV_View *view, String8 filter, E_Eval eval } // rjf: if this expr has a sibling, push another task to continue the chain - if(t->eval.expr->next != &e_expr_nil) + if(t->next_expr != &e_expr_nil) { Task *task = push_array(scratch.arena, Task, 1); task->next = t->next; t->next = task; task->parent_block = t->parent_block; - task->eval = e_eval_from_expr(t->eval.expr->next); + task->eval = e_eval_from_expr(t->next_expr); + task->next_expr = t->next_expr->next; task->child_id = t->child_id + 1; task->split_relative_idx = 0; task->default_expanded = t->default_expanded; @@ -2048,8 +2051,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.expr, &eval.irtree); - E_Eval deref_eval = e_eval_from_expr(deref_expr); + E_Eval deref_eval = e_eval_wrapf(eval, "*$"); need_new_task = 1; need_pop = 0; new_task.params = *params; @@ -2121,9 +2123,9 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string) //- rjf: middle step -> generate new task for next thing in expansion else { - E_Eval next_eval = {0}; + E_Eval next_eval = e_eval_nil; expand_data->expand_rule->range(arena, expand_data->expand_info.user_data, eval, params->filter, r1u64(task_idx-1, task_idx), &next_eval); - if(next_eval.expr != 0 && next_eval.expr != &e_expr_nil) + if(next_eval.expr != &e_expr_nil) { need_new_task = 1; need_pop = 0; diff --git a/src/raddbg/raddbg_eval.c b/src/raddbg/raddbg_eval.c index d8eeea5f..b122e5e1 100644 --- a/src/raddbg/raddbg_eval.c +++ b/src/raddbg/raddbg_eval.c @@ -683,9 +683,9 @@ E_TYPE_ACCESS_FUNCTION_DEF(cfgs) { String8 rhs_name = expr->first->next->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)) + if(str8_match(str8_prefix(rhs_name, 1), str8_lit("$"), 0)) { + id = u64_from_str8(str8_skip(rhs_name, 1), 16); cfg = rd_cfg_from_id(id); } }break; @@ -777,7 +777,7 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(cfgs) 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]; - evals_out[dst_idx] = e_eval_wrapf(eval, "$.$%I64d", cfg->id); + evals_out[dst_idx] = e_eval_from_stringf("$%I64x", cfg->id); } } } diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index fdd40619..7327ed07 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -1509,6 +1509,35 @@ rd_info_from_watch_row_cell(Arena *arena, EV_Row *row, EV_StringFlags string_fla { if(0){} + //- rjf: errors + else if(cell->eval.msgs.max_kind > E_MsgKind_Null && !(cell->flags & RD_WatchCellFlag_NoEval)) + { + RD_Font(RD_FontSlot_Main) + { + 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") + { + dr_fstrs_push_new(arena, &fstrs, ¶ms, + rd_icon_kind_text_table[RD_IconKind_WarningBig], + .font = rd_font_from_slot(RD_FontSlot_Icons), + .raster_flags = rd_raster_flags_from_slot(RD_FontSlot_Icons), + .color = ui_color_from_name(str8_lit("text"))); + dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); + for(E_Msg *msg = cell->eval.msgs.first; msg != 0; msg = msg->next) + { + DR_FStrList msg_fstrs = rd_fstrs_from_rich_string(arena, msg->text); + dr_fstrs_concat_in_place(&fstrs, &msg_fstrs); + if(msg->next) + { + dr_fstrs_push_new(arena, &fstrs, ¶ms, str8_lit(" ")); + } + } + } + result.expr_fstrs = fstrs; + } + } + //- rjf: cfg evaluation -> button for cfg else if(result.cfg != &rd_nil_cfg) { diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 3fd8a761..2503a391 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -2595,12 +2595,12 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe S64 column = cursor->column; Vec2F32 advance = fnt_dim_from_tag_size_string(line_box->font, line_box->font_size, 0, params->tab_size, str8_prefix(line_string, column-1)); F32 cursor_off_pixels = advance.x; - F32 cursor_thickness = ClampBot(4.f, line_box->font_size/6.f); + F32 cursor_thickness = ClampBot(1.f, floor_f32(line_box->font_size/10.f)); Rng2F32 cursor_rect = { - ui_box_text_position(line_box).x+cursor_off_pixels-cursor_thickness/2.f, + ui_box_text_position(line_box).x+cursor_off_pixels, line_box->rect.y0-params->font_size*0.125f, - ui_box_text_position(line_box).x+cursor_off_pixels+cursor_thickness/2.f, + ui_box_text_position(line_box).x+cursor_off_pixels+cursor_thickness, line_box->rect.y1+params->font_size*0.125f, }; Vec4F32 cursor_color = ui_color_from_name(str8_lit("cursor")); @@ -2608,7 +2608,7 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe { cursor_color.w *= 0.5f; } - dr_rect(cursor_rect, cursor_color, 1.f, 0, 1.f); + dr_rect(cursor_rect, cursor_color, 1.f, 0, 0.f); } // rjf: extra rendering for lines with line-info that match the hovered @@ -2849,10 +2849,10 @@ rd_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count_per_page, Tx //////////////////////////////// //~ rjf: UI Widgets: Fancy Labels -internal UI_Signal -rd_label(String8 string) +internal DR_FStrList +rd_fstrs_from_rich_string(Arena *arena, String8 string) { - Temp scratch = scratch_begin(0, 0); + Temp scratch = scratch_begin(&arena, 1); typedef U32 StringPartFlags; enum { @@ -2907,8 +2907,17 @@ rd_label(String8 string) fstr.params.color = rd_rgba_from_theme_color(RD_ThemeColor_CodeDefault); } } - dr_fstrs_push(scratch.arena, &fstrs, &fstr); + dr_fstrs_push(arena, &fstrs, &fstr); } + scratch_end(scratch); + return fstrs; +} + +internal UI_Signal +rd_label(String8 string) +{ + Temp scratch = scratch_begin(0, 0); + DR_FStrList fstrs = rd_fstrs_from_rich_string(scratch.arena, string); UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fstrs(box, &fstrs); UI_Signal sig = ui_signal_from_box(box); diff --git a/src/raddbg/raddbg_widgets.h b/src/raddbg/raddbg_widgets.h index d0622470..f801fc1a 100644 --- a/src/raddbg/raddbg_widgets.h +++ b/src/raddbg/raddbg_widgets.h @@ -160,6 +160,7 @@ internal B32 rd_do_txt_controls(TXT_TextInfo *info, String8 data, U64 line_count //////////////////////////////// //~ rjf: UI Widgets: Fancy Labels +internal DR_FStrList rd_fstrs_from_rich_string(Arena *arena, String8 string); internal UI_Signal rd_label(String8 string); internal UI_Signal rd_error_label(String8 string); internal B32 rd_help_label(String8 string); diff --git a/src/ui/ui_basic_widgets.c b/src/ui/ui_basic_widgets.c index c2e8c2e7..acf08194 100644 --- a/src/ui/ui_basic_widgets.c +++ b/src/ui/ui_basic_widgets.c @@ -143,24 +143,24 @@ internal UI_BOX_CUSTOM_DRAW(ui_line_edit_draw) TxtPt mark = draw_data->mark; F32 cursor_pixel_off = fnt_dim_from_tag_size_string(font, font_size, 0, tab_size, str8_prefix(edited_string, cursor.column-1)).x; F32 mark_pixel_off = fnt_dim_from_tag_size_string(font, font_size, 0, tab_size, str8_prefix(edited_string, mark.column-1)).x; - F32 cursor_thickness = ClampBot(4.f, font_size/6.f); + F32 cursor_thickness = ClampBot(1.f, floor_f32(font_size/10.f)); Rng2F32 cursor_rect = { - text_position.x + cursor_pixel_off - cursor_thickness*0.50f, + text_position.x + cursor_pixel_off, box->parent->parent->rect.y0+ui_top_font_size()*0.5f, - text_position.x + cursor_pixel_off + cursor_thickness*0.50f, + text_position.x + cursor_pixel_off + cursor_thickness, box->parent->parent->rect.y1-ui_top_font_size()*0.5f, }; Rng2F32 mark_rect = { - text_position.x + mark_pixel_off - cursor_thickness*0.50f, + text_position.x + mark_pixel_off - cursor_thickness, box->parent->parent->rect.y0+ui_top_font_size()*0.5f, - text_position.x + mark_pixel_off + cursor_thickness*0.50f, + text_position.x + mark_pixel_off + cursor_thickness, box->parent->parent->rect.y1-ui_top_font_size()*0.5f, }; Rng2F32 select_rect = union_2f32(cursor_rect, mark_rect); dr_rect(select_rect, select_color, font_size/2.f, 0, 1.f); - dr_rect(cursor_rect, cursor_color, 0.f, 0, 1.f); + dr_rect(cursor_rect, cursor_color, 0.f, 0, 0.f); } internal UI_Signal