lens inheritance-on-expansion, composability with lens types & accesses (dot operator, array index operator), plugging in visualizers, killing dead code, etc.

This commit is contained in:
Ryan Fleury
2025-04-10 14:18:57 -07:00
parent d15f9af4b7
commit c05c21cfa4
10 changed files with 450 additions and 385 deletions
+7 -6
View File
@@ -296,12 +296,13 @@ E_MemberKind;
typedef U32 E_TypeFlags;
enum
{
E_TypeFlag_Const = (1<<0),
E_TypeFlag_Volatile = (1<<1),
E_TypeFlag_IsPlainText = (1<<2),
E_TypeFlag_IsCodeText = (1<<3),
E_TypeFlag_IsPathText = (1<<4),
E_TypeFlag_EditableChildren = (1<<5),
E_TypeFlag_Const = (1<<0),
E_TypeFlag_Volatile = (1<<1),
E_TypeFlag_IsPlainText = (1<<2),
E_TypeFlag_IsCodeText = (1<<3),
E_TypeFlag_IsPathText = (1<<4),
E_TypeFlag_EditableChildren = (1<<5),
E_TypeFlag_InheritedOnAccess = (1<<6),
};
typedef struct E_Member E_Member;
+49 -4
View File
@@ -1242,6 +1242,7 @@ e_expr_unpoison(E_Expr *expr)
E_TYPE_ACCESS_FUNCTION_DEF(default)
{
Temp scratch = scratch_begin(&arena, 1);
E_IRTreeAndType result = {&e_irnode_nil};
switch(expr->kind)
{
@@ -1260,8 +1261,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default)
E_TypeKind check_type_kind = l_restype_kind;
if(l_restype_kind == E_TypeKind_Ptr ||
l_restype_kind == E_TypeKind_LRef ||
l_restype_kind == E_TypeKind_RRef ||
l_restype_kind == E_TypeKind_Lens)
l_restype_kind == E_TypeKind_RRef)
{
check_type_key = e_type_unwrap(e_type_direct_from_key(e_type_unwrap(l_restype)));
check_type_kind = e_type_kind_from_key(check_type_key);
@@ -1472,6 +1472,7 @@ E_TYPE_ACCESS_FUNCTION_DEF(default)
result.mode = mode;
}break;
}
scratch_end(scratch);
return result;
}
@@ -1482,6 +1483,7 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
E_TypeKeyList inherited_lenses = {0};
E_IRTreeAndType result = {&e_irnode_nil};
//////////////////////////////
@@ -1519,10 +1521,26 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
case E_ExprKind_MemberAccess:
case E_ExprKind_ArrayIndex:
{
// rjf: unpack left-hand-size
// rjf: unpack left-hand-side
E_Expr *lhs = expr->first;
E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs);
// rjf: gather inherited lenses from the left-hand-side
{
E_TypeKey k = lhs_irtree.type_key;
E_TypeKind kind = e_type_kind_from_key(k);
for(;kind == E_TypeKind_Lens;)
{
E_Type *lens_type = e_type_from_key__cached(k);
if(lens_type->flags & E_TypeFlag_InheritedOnAccess)
{
e_type_key_list_push_front(scratch.arena, &inherited_lenses, k);
}
k = e_type_direct_from_key(k);
kind = e_type_kind_from_key(k);
}
}
// 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;
@@ -2180,7 +2198,12 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
}
// 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);
result.type_key = e_type_key_cons(.kind = E_TypeKind_Lens,
.flags = lhs_type->flags,
.count = arg_count,
.args = args,
.direct_key = result.type_key,
.name = lhs_type->name);
scratch_end(scratch);
}
@@ -2790,6 +2813,28 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
e_expr_unpoison(t->expr);
}
//////////////////////////////
//- rjf: apply inherited lenses to the resultant type
//
if(inherited_lenses.count != 0)
{
E_Type *result_type = e_type_from_key__cached(result.type_key);
for(E_TypeKeyNode *n = inherited_lenses.first; n != 0; n = n->next)
{
E_Type *src_type = e_type_from_key__cached(n->v);
E_TypeKey dst_type_key = e_type_key_cons(.kind = src_type->kind,
.flags = src_type->flags,
.name = src_type->name,
.count = src_type->count,
.args = src_type->args,
.irgen = src_type->irgen,
.access = src_type->access,
.expand = src_type->expand,
.direct_key = result.type_key);
result.type_key = dst_type_key;
}
}
scratch_end(scratch);
ProfEnd();
return result;
+147 -102
View File
@@ -1337,7 +1337,8 @@ e_type_unwrap(E_TypeKey key)
E_TypeKind kind = e_type_kind_from_key(result);
if((E_TypeKind_FirstIncomplete <= kind && kind <= E_TypeKind_LastIncomplete) ||
kind == E_TypeKind_Modifier ||
kind == E_TypeKind_Alias)
kind == E_TypeKind_Alias ||
kind == E_TypeKind_Lens)
{
result = e_type_direct_from_key(result);
}
@@ -1889,6 +1890,91 @@ e_type_string_from_key(Arena *arena, E_TypeKey key)
return result;
}
internal E_TypeKey
e_default_expansion_type_from_key(E_TypeKey root_key)
{
E_TypeKey type_key = zero_struct;
for(E_TypeKey key = root_key;
!e_type_key_match(e_type_key_zero(), key);
key = e_type_direct_from_key(key))
{
B32 done = 1;
E_TypeKind kind = e_type_kind_from_key(key);
//- rjf: if we have pointers which point to a single thing (count = 1),
// or we have a lens, or we have a modifier node, then we will defer to
// the next type in the chain.
//
// if this pointer points to N things (count > 1), then we can use it for
// array-like expansion.
//
if(e_type_kind_is_pointer_or_ref(kind))
{
E_Type *type = e_type_from_key__cached(key);
if(!e_type_key_match(e_type_key_basic(E_TypeKind_Void), type->direct_type_key))
{
if(type->count == 1)
{
done = 0;
}
else if(type->count > 1)
{
type_key = key;
}
}
}
//- rjf: if we have lenses or modifiers in the type chain, then we will
// defer to the next type in the chain.
//
// NOTE(rjf): while it may seem like a lens type needs to do something
// different, because lenses sometimes want to define their own expansion
// rules, they would've redirected to an entirely different expansion
// hook. if we are in the default expansion hook, then the lenses do not
// impact the expansion at all (e.g. they are for other cosmetic things,
// like visualizers or integer radix changes), and so in that case we
// want to ignore them.
//
else if(kind == E_TypeKind_Lens ||
kind == E_TypeKind_Modifier)
{
done = 0;
}
//- rjf: if we've reached a struct-like, then we can use that for
// struct-like expansion.
else if(kind == E_TypeKind_Struct ||
kind == E_TypeKind_Union ||
kind == E_TypeKind_Class ||
kind == E_TypeKind_Set)
{
type_key = key;
}
//- rjf: if we've reached an enum-like, then we can use that for
// enum-like expansion.
else if(kind == E_TypeKind_Enum)
{
type_key = key;
}
//- rjf: if we've reached an array, then we can use that for array-like
// expansion.
else if(kind == E_TypeKind_Array)
{
type_key = key;
}
//- rjf: if we're done, then just break.
if(done)
{
break;
}
}
return type_key;
}
//- rjf: type key data structures
internal void
@@ -1900,6 +1986,15 @@ e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key)
list->count += 1;
}
internal void
e_type_key_list_push_front(Arena *arena, E_TypeKeyList *list, E_TypeKey key)
{
E_TypeKeyNode *n = push_array(arena, E_TypeKeyNode, 1);
n->v = key;
SLLQueuePushFront(list->first, list->last, n);
list->count += 1;
}
internal E_TypeKeyList
e_type_key_list_copy(Arena *arena, E_TypeKeyList *src)
{
@@ -2105,47 +2200,48 @@ 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) ||
type_kind == E_TypeKind_Lens)
//- rjf: try to extract a struct-like type key, enum-like, or array-like
// type key, for expansion
E_TypeKey expand_type_key = e_default_expansion_type_from_key(irtree->type_key);
//- rjf: struct type? -> use the struct type for expansion
B32 did_expansion = 0;
if(!did_expansion)
{
E_Type *type = e_type_from_key__cached(type_key);
result.expr_count = type->count;
if(type->count == 1 || type_kind == E_TypeKind_Lens)
E_TypeKind struct_type_kind = e_type_kind_from_key(expand_type_key);
if(struct_type_kind == E_TypeKind_Struct ||
struct_type_kind == E_TypeKind_Class ||
struct_type_kind == E_TypeKind_Union)
{
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;
}
E_MemberArray data_members = e_type_data_members_from_key_filter__cached(expand_type_key, filter);
result.expr_count = data_members.count;
did_expansion = 1;
}
}
else if(type_kind == E_TypeKind_Struct ||
type_kind == E_TypeKind_Class ||
type_kind == E_TypeKind_Union)
//- rjf: array-like type? -> use the array-like for expansion
if(!did_expansion)
{
E_MemberArray data_members = e_type_data_members_from_key_filter__cached(type_key, filter);
result.expr_count = data_members.count;
E_TypeKind array_type_kind = e_type_kind_from_key(expand_type_key);
if(array_type_kind == E_TypeKind_Array ||
array_type_kind == E_TypeKind_Ptr)
{
E_Type *array_type = e_type_from_key__cached(expand_type_key);
result.expr_count = array_type->count;
did_expansion = 1;
}
}
else if(type_kind == E_TypeKind_Enum)
//- rjf: enum-like type? -> use the enum-like for expansion
if(!did_expansion)
{
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;
E_TypeKind enum_type_kind = e_type_kind_from_key(expand_type_key);
if(enum_type_kind == E_TypeKind_Enum)
{
E_Type *enum_type = e_type_from_key__cached(expand_type_key);
result.expr_count = enum_type->count;
did_expansion = 1;
}
}
}
return result;
@@ -2155,70 +2251,17 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default)
{
Temp scratch = scratch_begin(&arena, 1);
{
//- rjf: unpack type of expression
E_IRTreeAndType lhs_irtree = *irtree;
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) ||
lhs_type_kind == E_TypeKind_Lens)
{
E_Type *lhs_type = e_type_from_key__cached(lhs_type_key);
if((lhs_type->count == 1 ||
lhs_type_kind == E_TypeKind_Lens) &&
(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: try to extract a struct-like type key, enum-like, or array-like
// type key, for expansion
E_TypeKey expand_type_key = e_default_expansion_type_from_key(irtree->type_key);
E_TypeKind expand_type_kind = e_type_kind_from_key(expand_type_key);
//- rjf: struct case -> the lookup-range will return a range of members
if(do_struct_range)
if(expand_type_kind == E_TypeKind_Struct ||
expand_type_kind == E_TypeKind_Class ||
expand_type_kind == E_TypeKind_Union)
{
E_MemberArray data_members = e_type_data_members_from_key_filter__cached(struct_type_key, filter);
E_MemberArray data_members = e_type_data_members_from_key_filter__cached(expand_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);
@@ -2226,14 +2269,14 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default)
{
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);
exprs_out[idx] = e_expr_irext_member_access(arena, expr, irtree, member_name);
}
}
//- rjf: enum case -> the lookup-range will return a range of enum constants
else if(do_enum_range)
else if(expand_type_kind == E_TypeKind_Enum)
{
E_Type *type = e_type_from_key__cached(enum_type_key);
E_Type *type = e_type_from_key__cached(expand_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);
@@ -2241,17 +2284,19 @@ E_TYPE_EXPAND_RANGE_FUNCTION_DEF(default)
{
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);
exprs_out[idx] = e_expr_irext_member_access(arena, expr, irtree, member_name);
}
}
//- rjf: ptr case -> the lookup-range will return a range of dereferences
else if(do_index_range)
else if(expand_type_kind == E_TypeKind_Ptr ||
expand_type_kind == E_TypeKind_Array ||
expand_type_kind == E_TypeKind_Set)
{
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);
exprs_out[idx] = e_expr_irext_array_index(arena, expr, irtree, idx_range.min + idx);
}
}
}
+2
View File
@@ -264,9 +264,11 @@ internal E_Member *e_type_member_from_array_name(E_MemberArray *members, String8
internal void e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec, B32 skip_return);
internal void e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 prec);
internal String8 e_type_string_from_key(Arena *arena, E_TypeKey key);
internal E_TypeKey e_default_expansion_type_from_key(E_TypeKey key);
//- rjf: type key data structures
internal void e_type_key_list_push(Arena *arena, E_TypeKeyList *list, E_TypeKey key);
internal void e_type_key_list_push_front(Arena *arena, E_TypeKeyList *list, E_TypeKey key);
internal E_TypeKeyList e_type_key_list_copy(Arena *arena, E_TypeKeyList *src);
internal E_String2TypeKeyMap e_string2typekey_map_make(Arena *arena, U64 slots_count);
internal void e_string2typekey_map_insert(Arena *arena, E_String2TypeKeyMap *map, String8 string, E_TypeKey key);