eval space generation, to gracefully mark cached evaluations as dirty when desired

This commit is contained in:
Ryan Fleury
2025-04-26 12:33:48 -07:00
parent ea18e58903
commit 2092f5ca69
13 changed files with 248 additions and 438 deletions
-398
View File
@@ -1,398 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Bundled Evaluation Functions
#if 0
internal E_Eval
e_eval_from_expr(Arena *arena, E_Expr *expr)
{
ProfBeginFunction();
E_IRTreeAndType irtree = e_push_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);
E_Eval eval =
{
.value = interp.value,
.space = interp.space,
.expr = expr,
.irtree = irtree,
.bytecode = bytecode,
.code = interp.code,
};
e_msg_list_concat_in_place(&eval.msgs, &irtree.msgs);
if(E_InterpretationCode_Good < eval.code && eval.code < E_InterpretationCode_COUNT)
{
e_msg(arena, &eval.msgs, E_MsgKind_InterpretationError, 0, e_interpretation_code_display_strings[eval.code]);
}
ProfEnd();
return eval;
}
internal E_Eval
e_eval_from_string(Arena *arena, String8 string)
{
ProfBeginFunction();
ProfBegin("e_eval_from_string (%.*s)", str8_varg(string));
E_Parse parse = e_parse_from_string(string);
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(parse.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);
E_Eval eval =
{
.value = interp.value,
.space = interp.space,
.expr = parse.expr,
.irtree = irtree,
.bytecode = bytecode,
.code = interp.code,
};
e_msg_list_concat_in_place(&eval.msgs, &irtree.msgs);
if(E_InterpretationCode_Good < eval.code && eval.code < E_InterpretationCode_COUNT)
{
e_msg(arena, &eval.msgs, E_MsgKind_InterpretationError, 0, e_interpretation_code_display_strings[eval.code]);
}
ProfEnd();
ProfEnd();
return eval;
}
internal E_Eval
e_eval_from_stringf(Arena *arena, char *fmt, ...)
{
Temp scratch = scratch_begin(&arena, 1);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
E_Eval eval = e_eval_from_string(arena, string);
va_end(args);
scratch_end(scratch);
return eval;
}
internal E_Eval
e_dynamically_typed_eval_from_eval(E_Eval eval)
{
E_TypeKey type_key = eval.irtree.type_key;
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(e_type_state != 0 &&
e_interpret_ctx != 0 &&
e_interpret_ctx->space_read != 0 &&
e_interpret_ctx->module_base != 0 &&
type_kind == E_TypeKind_Ptr)
{
Temp scratch = scratch_begin(0, 0);
E_TypeKey ptee_type_key = e_type_key_unwrap(type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind ptee_type_kind = e_type_kind_from_key(ptee_type_key);
if(ptee_type_kind == E_TypeKind_Struct || ptee_type_kind == E_TypeKind_Class)
{
E_Type *ptee_type = e_type_from_key__cached(ptee_type_key);
B32 has_vtable = 0;
for(U64 idx = 0; idx < ptee_type->count; idx += 1)
{
if(ptee_type->members[idx].kind == E_MemberKind_VirtualMethod)
{
has_vtable = 1;
break;
}
}
if(has_vtable)
{
U64 ptr_vaddr = eval.value.u64;
U64 addr_size = e_type_byte_size_from_key(e_type_key_unwrap(type_key, E_TypeUnwrapFlag_AllDecorative));
U64 class_base_vaddr = 0;
U64 vtable_vaddr = 0;
if(e_space_read(eval.space, &class_base_vaddr, r1u64(ptr_vaddr, ptr_vaddr+addr_size)) &&
e_space_read(eval.space, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size)))
{
Arch arch = e_base_ctx->primary_module->arch;
U32 rdi_idx = 0;
RDI_Parsed *rdi = 0;
U64 module_base = 0;
for(U64 idx = 0; idx < e_base_ctx->modules_count; idx += 1)
{
if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vtable_vaddr))
{
arch = e_base_ctx->modules[idx].arch;
rdi_idx = (U32)idx;
rdi = e_base_ctx->modules[idx].rdi;
module_base = e_base_ctx->modules[idx].vaddr_range.min;
break;
}
}
if(rdi != 0)
{
U64 vtable_voff = vtable_vaddr - module_base;
U64 global_idx = rdi_vmap_idx_from_section_kind_voff(rdi, RDI_SectionKind_GlobalVMap, vtable_voff);
RDI_GlobalVariable *global_var = rdi_element_from_name_idx(rdi, GlobalVariables, global_idx);
if(global_var->link_flags & RDI_LinkFlag_TypeScoped)
{
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx);
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, rdi_idx);
E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 1, 0);
eval.irtree.type_key = ptr_to_derived_type_key;
}
}
}
}
}
scratch_end(scratch);
}
return eval;
}
internal E_Value
e_value_from_string(String8 string)
{
Temp scratch = scratch_begin(0, 0);
E_Eval eval = e_eval_from_string(scratch.arena, string);
E_Eval value_eval = e_value_eval_from_eval(eval);
E_Value result = value_eval.value;
scratch_end(scratch);
return result;
}
internal E_Value
e_value_from_stringf(char *fmt, ...)
{
Temp scratch = scratch_begin(0, 0);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
E_Value result = e_value_from_string(string);
va_end(args);
scratch_end(scratch);
return result;
}
internal E_Value
e_value_from_expr(E_Expr *expr)
{
Temp scratch = scratch_begin(0, 0);
E_Eval eval = e_eval_from_expr(scratch.arena, expr);
E_Eval value_eval = e_value_eval_from_eval(eval);
E_Value result = value_eval.value;
scratch_end(scratch);
return result;
}
internal E_Value
e_value_from_eval(E_Eval eval)
{
E_Eval value_eval = e_value_eval_from_eval(eval);
E_Value result = value_eval.value;
return result;
}
internal E_Eval
e_eval_wrap(Arena *arena, E_Eval eval, String8 string)
{
E_IRTreeAndType *prev_overridden_irtree = e_ir_state->overridden_irtree;
e_ir_state->overridden_irtree = &eval.irtree;
E_Eval wrapped_eval = e_eval_from_string(arena, string);
e_ir_state->overridden_irtree = prev_overridden_irtree;
return wrapped_eval;
}
internal E_Eval
e_eval_wrapf(Arena *arena, E_Eval eval, char *fmt, ...)
{
Temp scratch = scratch_begin(&arena, 1);
va_list args;
va_start(args, fmt);
String8 string = push_str8fv(scratch.arena, fmt, args);
E_Eval result = e_eval_wrap(arena, eval, string);
va_end(args);
scratch_end(scratch);
return result;
}
#endif
internal U64
e_base_offset_from_eval(E_Eval eval)
{
if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative))))
{
eval = e_value_eval_from_eval(eval);
}
return eval.value.u64;
}
internal Rng1U64
e_range_from_eval(E_Eval eval)
{
U64 size = 0;
E_Type *type = e_type_from_key__cached(eval.irtree.type_key);
if(type->kind == E_TypeKind_Lens)
{
for EachIndex(idx, type->count)
{
E_Expr *arg = type->args[idx];
if(arg->kind == E_ExprKind_Define && str8_match(arg->first->string, str8_lit("size"), 0))
{
size = e_value_from_expr(arg->first->next).u64;
break;
}
}
}
E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
E_TypeKey direct_type_key = e_type_key_unwrap(type_key, E_TypeUnwrapFlag_All);
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
if(size == 0 && e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct ||
direct_type_kind == E_TypeKind_Union ||
direct_type_kind == E_TypeKind_Class ||
direct_type_kind == E_TypeKind_Array))
{
size = e_type_byte_size_from_key(direct_type_key);
}
if(size == 0 && eval.irtree.mode == E_Mode_Offset && (type_kind == E_TypeKind_Struct ||
type_kind == E_TypeKind_Union ||
type_kind == E_TypeKind_Class ||
type_kind == E_TypeKind_Array))
{
size = e_type_byte_size_from_key(type_key);
}
if(size == 0)
{
size = KB(16);
}
Rng1U64 result = {0};
result.min = e_base_offset_from_eval(eval);
result.max = result.min + size;
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};
//- rjf: begin expression
String8 expr_text = string;
str8_list_pushf(scratch.arena, &strings, "`%S`\n", expr_text);
//- rjf: parse
E_Parse parse = e_push_parse_from_string(scratch.arena, expr_text);
{
typedef struct Task Task;
struct Task
{
Task *next;
E_Expr *expr;
S32 indent;
};
E_TokenArray tokens = parse.tokens;
str8_list_pushf(scratch.arena, &strings, " tokens:\n");
for EachIndex(idx, tokens.count)
{
E_Token token = tokens.v[idx];
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);
}
str8_list_pushf(scratch.arena, &strings, " expr:\n");
Task start_task = {0, parse.expr, 2};
Task *first_task = &start_task;
for(Task *t = first_task; t != 0; t = t->next)
{
E_Expr *expr = t->expr;
str8_list_pushf(scratch.arena, &strings, "%.*s%S", (int)t->indent*4, indent_spaces, e_expr_kind_strings[expr->kind]);
switch(expr->kind)
{
default:{}break;
case E_ExprKind_LeafU64:
{
str8_list_pushf(scratch.arena, &strings, " (%I64u)", expr->value.u64);
}break;
case E_ExprKind_LeafIdentifier:
{
str8_list_pushf(scratch.arena, &strings, " (`%S`)", expr->string);
}break;
}
str8_list_pushf(scratch.arena, &strings, "\n");
Task *last_task = t;
for(E_Expr *child = expr->first; child != &e_expr_nil; child = child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
task->next = last_task->next;
last_task->next = task;
task->expr = child;
task->indent = t->indent+1;
last_task = task;
}
}
}
//- rjf: type
E_IRTreeAndType irtree = e_push_irtree_and_type_from_expr(scratch.arena, 0, 0, 0, parse.expr);
{
str8_list_pushf(scratch.arena, &strings, " type:\n");
S32 indent = 2;
for(E_TypeKey type_key = irtree.type_key;
!e_type_key_match(e_type_key_zero(), type_key);
type_key = e_type_key_direct(type_key),
indent += 1)
{
E_Type *type = e_type_from_key(scratch.arena, type_key);
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;
struct Task
{
Task *next;
E_IRNode *irnode;
S32 indent;
};
str8_list_pushf(scratch.arena, &strings, " ir_tree:\n");
Task start_task = {0, irtree.root, 2};
Task *first_task = &start_task;
for(Task *t = first_task; t != 0; t = t->next)
{
E_IRNode *irnode = t->irnode;
str8_list_pushf(scratch.arena, &strings, "%.*s", (int)t->indent*4, indent_spaces);
switch(irnode->op)
{
default:{}break;
#define X(name) case RDI_EvalOp_##name:{str8_list_pushf(scratch.arena, &strings, #name);}break;
RDI_EvalOp_XList
#undef X
}
if(irnode->value.u64 != 0)
{
str8_list_pushf(scratch.arena, &strings, " (%I64u)", irnode->value.u64);
}
str8_list_pushf(scratch.arena, &strings, "\n");
Task *last_task = t;
for(E_IRNode *child = irnode->first; child != &e_irnode_nil; child = child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
task->next = last_task->next;
last_task->next = task;
task->irnode = child;
task->indent = t->indent+1;
last_task = task;
}
}
}
str8_list_pushf(scratch.arena, &strings, "\n");
String8 result = str8_list_join(arena, &strings, 0);
scratch_end(scratch);
return result;
}
-32
View File
@@ -1,32 +0,0 @@
// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef EVAL_BUNDLES_H
#define EVAL_BUNDLES_H
////////////////////////////////
//~ rjf: Bundled Evaluation Functions
#if 0
internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr);
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_dynamically_typed_eval_from_eval(E_Eval eval);
internal E_Eval e_value_eval_from_eval(E_Eval eval);
internal E_Value e_value_from_string(String8 string);
internal E_Value e_value_from_stringf(char *fmt, ...);
internal E_Value e_value_from_expr(E_Expr *expr);
internal E_Value e_value_from_eval(E_Eval eval);
internal E_Eval e_eval_wrap(Arena *arena, E_Eval eval, String8 string);
internal E_Eval e_eval_wrapf(Arena *arena, E_Eval eval, char *fmt, ...);;
#endif
internal U64 e_base_offset_from_eval(E_Eval eval);
internal Rng1U64 e_range_from_eval(E_Eval eval);
////////////////////////////////
//~ rjf: Debug Logging Functions
internal String8 e_debug_log_from_expr_string(Arena *arena, String8 string);
#endif // EVAL_BUNDLES_H
+192 -1
View File
@@ -727,7 +727,10 @@ e_key_from_string(String8 string)
E_CacheNode *node = 0;
for(E_CacheNode *n = slot->first; n != 0; n = n->string_next)
{
if(e_key_match(parent_key, n->bundle.parent_key) && str8_match(n->bundle.string, string, 0))
if(e_key_match(parent_key, n->bundle.parent_key) &&
str8_match(n->bundle.string, string, 0) &&
(n->bundle.interpretation.space.kind == E_SpaceKind_Null ||
e_space_gen(n->bundle.interpretation.space) == n->bundle.space_gen))
{
node = n;
break;
@@ -859,6 +862,7 @@ e_interpretation_from_bundle(E_CacheBundle *bundle)
e_msg(e_cache->arena, &bundle->msgs, E_MsgKind_InterpretationError, 0, e_interpretation_code_display_strings[interpret.code]);
}
bundle->interpretation = interpret;
bundle->space_gen = e_space_gen(interpret.space);
}
E_Interpretation interpret = bundle->interpretation;
return interpret;
@@ -1113,3 +1117,190 @@ e_key_wrapf(E_Key key, char *fmt, ...)
scratch_end(scratch);
return result;
}
////////////////////////////////
//~ rjf: Eval Info Extraction
internal U64
e_base_offset_from_eval(E_Eval eval)
{
if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative))))
{
eval = e_value_eval_from_eval(eval);
}
return eval.value.u64;
}
internal Rng1U64
e_range_from_eval(E_Eval eval)
{
U64 size = 0;
E_Type *type = e_type_from_key__cached(eval.irtree.type_key);
if(type->kind == E_TypeKind_Lens)
{
for EachIndex(idx, type->count)
{
E_Expr *arg = type->args[idx];
if(arg->kind == E_ExprKind_Define && str8_match(arg->first->string, str8_lit("size"), 0))
{
size = e_value_from_expr(arg->first->next).u64;
break;
}
}
}
E_TypeKey type_key = e_type_key_unwrap(eval.irtree.type_key, E_TypeUnwrapFlag_AllDecorative);
E_TypeKind type_kind = e_type_kind_from_key(type_key);
E_TypeKey direct_type_key = e_type_key_unwrap(type_key, E_TypeUnwrapFlag_All);
E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key);
if(size == 0 && e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct ||
direct_type_kind == E_TypeKind_Union ||
direct_type_kind == E_TypeKind_Class ||
direct_type_kind == E_TypeKind_Array))
{
size = e_type_byte_size_from_key(direct_type_key);
}
if(size == 0 && eval.irtree.mode == E_Mode_Offset && (type_kind == E_TypeKind_Struct ||
type_kind == E_TypeKind_Union ||
type_kind == E_TypeKind_Class ||
type_kind == E_TypeKind_Array))
{
size = e_type_byte_size_from_key(type_key);
}
if(size == 0)
{
size = KB(16);
}
Rng1U64 result = {0};
result.min = e_base_offset_from_eval(eval);
result.max = result.min + size;
return result;
}
////////////////////////////////
//~ rjf: Debug 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};
//- rjf: begin expression
String8 expr_text = string;
str8_list_pushf(scratch.arena, &strings, "`%S`\n", expr_text);
//- rjf: parse
E_Parse parse = e_push_parse_from_string(scratch.arena, expr_text);
{
typedef struct Task Task;
struct Task
{
Task *next;
E_Expr *expr;
S32 indent;
};
E_TokenArray tokens = parse.tokens;
str8_list_pushf(scratch.arena, &strings, " tokens:\n");
for EachIndex(idx, tokens.count)
{
E_Token token = tokens.v[idx];
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);
}
str8_list_pushf(scratch.arena, &strings, " expr:\n");
Task start_task = {0, parse.expr, 2};
Task *first_task = &start_task;
for(Task *t = first_task; t != 0; t = t->next)
{
E_Expr *expr = t->expr;
str8_list_pushf(scratch.arena, &strings, "%.*s%S", (int)t->indent*4, indent_spaces, e_expr_kind_strings[expr->kind]);
switch(expr->kind)
{
default:{}break;
case E_ExprKind_LeafU64:
{
str8_list_pushf(scratch.arena, &strings, " (%I64u)", expr->value.u64);
}break;
case E_ExprKind_LeafIdentifier:
{
str8_list_pushf(scratch.arena, &strings, " (`%S`)", expr->string);
}break;
}
str8_list_pushf(scratch.arena, &strings, "\n");
Task *last_task = t;
for(E_Expr *child = expr->first; child != &e_expr_nil; child = child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
task->next = last_task->next;
last_task->next = task;
task->expr = child;
task->indent = t->indent+1;
last_task = task;
}
}
}
//- rjf: type
E_IRTreeAndType irtree = e_push_irtree_and_type_from_expr(scratch.arena, 0, 0, 0, parse.expr);
{
str8_list_pushf(scratch.arena, &strings, " type:\n");
S32 indent = 2;
for(E_TypeKey type_key = irtree.type_key;
!e_type_key_match(e_type_key_zero(), type_key);
type_key = e_type_key_direct(type_key),
indent += 1)
{
E_Type *type = e_type_from_key(scratch.arena, type_key);
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;
struct Task
{
Task *next;
E_IRNode *irnode;
S32 indent;
};
str8_list_pushf(scratch.arena, &strings, " ir_tree:\n");
Task start_task = {0, irtree.root, 2};
Task *first_task = &start_task;
for(Task *t = first_task; t != 0; t = t->next)
{
E_IRNode *irnode = t->irnode;
str8_list_pushf(scratch.arena, &strings, "%.*s", (int)t->indent*4, indent_spaces);
switch(irnode->op)
{
default:{}break;
#define X(name) case RDI_EvalOp_##name:{str8_list_pushf(scratch.arena, &strings, #name);}break;
RDI_EvalOp_XList
#undef X
}
if(irnode->value.u64 != 0)
{
str8_list_pushf(scratch.arena, &strings, " (%I64u)", irnode->value.u64);
}
str8_list_pushf(scratch.arena, &strings, "\n");
Task *last_task = t;
for(E_IRNode *child = irnode->first; child != &e_irnode_nil; child = child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
task->next = last_task->next;
last_task->next = task;
task->irnode = child;
task->indent = t->indent+1;
last_task = task;
}
}
}
str8_list_pushf(scratch.arena, &strings, "\n");
String8 result = str8_list_join(arena, &strings, 0);
scratch_end(scratch);
return result;
}
+14 -1
View File
@@ -682,6 +682,7 @@ struct E_AutoHookParams
////////////////////////////////
//~ rjf: Evaluation Context
typedef U64 E_SpaceGenFunction(void *user_data, E_Space space);
typedef B32 E_SpaceRWFunction(void *user_data, E_Space space, void *out, Rng1U64 offset_range);
//- rjf: base context
@@ -703,6 +704,7 @@ struct E_BaseCtx
// rjf: space hooks
void *space_rw_user_data;
E_SpaceGenFunction *space_gen;
E_SpaceRWFunction *space_read;
E_SpaceRWFunction *space_write;
};
@@ -887,6 +889,7 @@ struct E_CacheBundle
E_IRTreeAndType irtree;
String8 bytecode;
E_Interpretation interpretation;
U64 space_gen;
E_MsgList msgs;
};
@@ -1143,7 +1146,6 @@ internal E_Eval e_value_eval_from_eval(E_Eval eval);
#define e_eval_from_stringf(...) e_eval_from_key(e_key_from_stringf(__VA_ARGS__))
#define e_value_from_string(string) e_value_eval_from_eval(e_eval_from_string(string)).value
#define e_value_from_stringf(...) e_value_eval_from_eval(e_eval_from_stringf(__VA_ARGS__)).value
// TODO(rjf): (replace the old bundle APIs here)
//- rjf: expr-based helpers
#define e_eval_from_expr(expr) e_eval_from_key(e_key_from_expr(expr))
@@ -1167,4 +1169,15 @@ internal E_Key e_key_wrapf(E_Key key, char *fmt, ...);
#define e_eval_wrap(eval, string) e_eval_from_key(e_key_wrap((eval).key, (string)))
#define e_eval_wrapf(eval, ...) e_eval_from_key(e_key_wrapf((eval).key, __VA_ARGS__))
////////////////////////////////
//~ rjf: Eval Info Extraction
internal U64 e_base_offset_from_eval(E_Eval eval);
internal Rng1U64 e_range_from_eval(E_Eval eval);
////////////////////////////////
//~ rjf: Debug Functions
internal String8 e_debug_log_from_expr_string(Arena *arena, String8 string);
#endif // EVAL_CORE_H
-1
View File
@@ -6,4 +6,3 @@
#include "eval/eval_parse.c"
#include "eval/eval_ir.c"
#include "eval/eval_interpret.c"
#include "eval/eval_bundles.c"
-1
View File
@@ -9,6 +9,5 @@
#include "eval/eval_parse.h"
#include "eval/eval_ir.h"
#include "eval/eval_interpret.h"
#include "eval/eval_bundles.h"
#endif // EVAL_INC_H
+11
View File
@@ -55,6 +55,17 @@ e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rdi, U64 ip_voff
////////////////////////////////
//~ rjf: Space Reading Helpers
internal U64
e_space_gen(E_Space space)
{
U64 result = 0;
if(e_base_ctx->space_gen != 0)
{
result = e_base_ctx->space_gen(e_base_ctx->space_rw_user_data, space);
}
return result;
}
internal B32
e_space_read(E_Space space, void *out, Rng1U64 range)
{
+1
View File
@@ -35,6 +35,7 @@ internal void e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rd
////////////////////////////////
//~ rjf: Space Reading Helpers
internal U64 e_space_gen(E_Space space);
internal B32 e_space_read(E_Space space, void *out, Rng1U64 range);
internal B32 e_space_write(E_Space space, void *in, Rng1U64 range);
+1 -1
View File
@@ -379,7 +379,7 @@ RD_NameSchemaInfo rd_name_schema_info_table[21] =
{str8_lit_comp("window"), str8_lit_comp("x:\n{\n //- rjf: text rasterization settings\n @default(1) @display_name('Smooth UI Text') @description(\"Controls whether or not UI text is fully anti-aliased, for a smoother appearance.\")\n 'smooth_ui_text': bool,\n @default(1) @display_name('Hint UI Text') @description(\"Controls whether or not UI text is hinted, for better text readability at small sizes.\")\n 'hint_ui_text': bool,\n @default(0) @display_name('Smooth Code Text') @description(\"Controls whether or not code text is fully anti-aliased, for a smoother appearance.\")\n 'smooth_code_text': bool,\n @default(1) @display_name('Hint Code Text') @description(\"Controls whether or not code text is hinted, for better text readability at small sizes.\")\n 'hint_code_text': bool,\n @default(11) @display_name('Window Font Size') @description(\"Controls the window's default font size. Does not apply to tabs with their own font size set.\")\n 'font_size': @range[6, 72] u64,\n\n //- rjf: size settings\n @default(3.f) @display_name('Window Row Height') @description(\"Controls the window's default row height, in multiples of the font size. Does not apply to tabs with their own row height set.\")\n 'row_height': @range[1.75f, 5.f] f32,\n @default(3.f) @description(\"Controls the height of tabs, in multiples of the font size.\")\n 'tab_height': @range[1.75f, 5.f] f32,\n}\n")},
{str8_lit_comp("tab"), str8_lit_comp("x:\n{\n @default(11) @display_name('Tab Font Size') @description(\"Controls the tab's font size.\")\n 'font_size': @range[6, 72] u64,\n}\n")},
{str8_lit_comp("watch"), str8_lit_comp("@inherit(tab) x:\n{\n @default(3.f) @display_name('Tab Row Height') @description(\"Controls the tab's row height, in multiples of the font size.\")\n 'row_height': @range[1.75f, 5.f] f32,\n 'label': code_string,\n @description(\"The root expression which is evaluated to produce the watch window.\")\n 'expression': code_string,\n @no_expand 'watches': query,\n}\n")},
{str8_lit_comp("text"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"The language that the text should be interpreted as being within. Used for syntax highlighting and other parsing features.\")\n 'lang': lang,\n @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers':bool,\n @default(0) @display_name('Transient') @description(\"Controls whether or not this tab will be automatically replaced by the debugger when it snaps to new source code locations.\")\n 'auto': bool,\n @description(\"An expression to describe data which should be viewed as text or code.\")\n 'expression': code_string,\n}\n")},
{str8_lit_comp("text"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression to describe data which should be viewed as text or code.\")\n 'expression': code_string,\n @description(\"The language that the text should be interpreted as being within. Used for syntax highlighting and other parsing features.\")\n 'lang': lang,\n @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers':bool,\n @default(0) @display_name('Transient') @description(\"Controls whether or not this tab will be automatically replaced by the debugger when it snaps to new source code locations.\")\n 'auto': bool,\n}\n")},
{str8_lit_comp("disasm"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression to describe the base address or offset of the disassembly.\")\n 'expression': code_string,\n 'arch': arch,\n 'syntax': dasm_syntax,\n 'size': code_string,\n @default(1) @description(\"Controls whether or not addresses are shown in the disassembly text.\")\n 'show_addresses': bool,\n @default(0) @description(\"Controls whether or not code bytes are shown in the disassembly text.\")\n 'show_code_bytes': bool,\n @default(1) @description(\"Controls whether or not source lines, corresponding to disassembly instruction ranges, are shown in the disassembly text.\")\n 'show_source_lines': bool,\n @default(1) @description(\"Controls whether or not disassembly text is decorated with symbol names.\")\n 'show_symbol_names': bool,\n @default(1) @description(\"Controls whether or not line numbers are shown.\")\n 'show_line_numbers': bool,\n}\n")},
{str8_lit_comp("memory"), str8_lit_comp("@inherit(tab) x:\n{\n @description(\"An expression to describe the base address or offset of the memory view.\")\n 'expression': code_string,\n @description(\"The number of bytes of the viewed memory range.\")\n 'size': code_string,\n @default(16) @description(\"The number of columns to build before building new rows.\")\n 'num_columns': @range[1, 64] u64,\n @default(1) @description(\"The number of bytes that each cell should represent.\")\n 'bytes_per_cell': @range[1, 8] u64,\n}\n")},
{str8_lit_comp("bitmap"), str8_lit_comp("@inherit(tab) x:\n{\n @display_name(\"Base Pointer\") @description(\"An expression to describe the base address or offset of the bitmap data.\")\n 'expression': code_string,\n @order(0) 'w': u64,\n @order(1) 'h': u64,\n @display_name(\"Bitmap Format\") @description(\"The pixel format that the bitmap data should be interpreted as being within.\")\n 'fmt': tex2dformat,\n}\n")},
+2 -2
View File
@@ -327,14 +327,14 @@ RD_VocabTable:
```
@inherit(tab) x:
{
@description("An expression to describe data which should be viewed as text or code.")
'expression': code_string,
@description("The language that the text should be interpreted as being within. Used for syntax highlighting and other parsing features.")
'lang': lang,
@default(1) @description("Controls whether or not line numbers are shown.")
'show_line_numbers':bool,
@default(0) @display_name('Transient') @description("Controls whether or not this tab will be automatically replaced by the debugger when it snaps to new source code locations.")
'auto': bool,
@description("An expression to describe data which should be viewed as text or code.")
'expression': code_string,
}
```
}
+23 -1
View File
@@ -276,6 +276,8 @@ rd_name_release(String8 string)
internal RD_Cfg *
rd_cfg_alloc(void)
{
rd_state->cfg_change_gen += 1;
// rjf: allocate
RD_Cfg *result = rd_state->free_cfg;
{
@@ -318,6 +320,8 @@ rd_cfg_alloc(void)
internal void
rd_cfg_release(RD_Cfg *cfg)
{
rd_state->cfg_change_gen += 1;
Temp scratch = scratch_begin(0, 0);
// rjf: unhook from context
@@ -1561,6 +1565,21 @@ rd_cmd_name_from_eval(E_Eval eval)
//- rjf: eval space reads/writes
internal U64
rd_eval_space_gen(void *u, E_Space space)
{
U64 result = 0;
switch(space.kind)
{
case RD_EvalSpaceKind_MetaCfg:
case RD_EvalSpaceKind_MetaQuery:
{
result = rd_state->cfg_change_gen;
}break;
}
return result;
}
internal B32
rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
{
@@ -2820,6 +2839,7 @@ rd_view_ui(Rng2F32 rect)
//
if(state_dirty) ProfScope("state -> viz blocks")
{
eval = e_eval_from_string(eval.string);
MemoryZeroStruct(&block_tree);
MemoryZeroStruct(&block_ranges);
if(implicit_root || is_first_frame)
@@ -11669,7 +11689,7 @@ rd_frame(void)
}
//- rjf: try menu bar operations
if(rd_setting_b32_from_name(str8_lit("focus_menu_bar_with_alt")))
if(rd_state->alt_menu_bar_enabled)
{
if(!take && event->kind == OS_EventKind_Press && event->key == OS_Key_Alt && event->modifiers == 0 && event->is_repeat == 0)
{
@@ -11836,6 +11856,7 @@ rd_frame(void)
ctx->primary_module = eval_modules_primary;
//- rjf: fill space hooks
ctx->space_gen = rd_eval_space_gen;
ctx->space_read = rd_eval_space_read;
ctx->space_write = rd_eval_space_write;
}
@@ -12518,6 +12539,7 @@ rd_frame(void)
////////////////////////////
//- rjf: process top-level graphical commands
//
rd_state->alt_menu_bar_enabled = rd_setting_b32_from_name(str8_lit("focus_menu_bar_with_alt"));
if(rd_state->frame_depth == 0)
{
for(;rd_next_cmd(&cmd);) RD_RegsScope()
+3
View File
@@ -599,6 +599,7 @@ struct RD_State
Arena *arena;
B32 quit;
B32 quit_after_success;
B32 alt_menu_bar_enabled;
S32 frame_depth;
U64 frame_eval_memread_endt_us;
@@ -715,6 +716,7 @@ struct RD_State
U64 cfg_id_gen;
RD_CfgID cfg_last_accessed_id;
RD_Cfg *cfg_last_accessed;
U64 cfg_change_gen;
// rjf: window state cache
U64 window_state_slots_count;
@@ -923,6 +925,7 @@ internal E_Space rd_eval_space_from_ctrl_entity(CTRL_Entity *entity, E_SpaceKind
internal String8 rd_cmd_name_from_eval(E_Eval eval);
//- rjf: eval space reads/writes
internal U64 rd_eval_space_gen(void *u, E_Space space);
internal B32 rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range);
internal B32 rd_eval_space_write(void *u, E_Space space, void *in, Rng1U64 range);
+1
View File
@@ -257,6 +257,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(schema)
{
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("string"), 0))
{
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPlainText);