further work on convergence, dead code elimination, and lens (view rule) calls

This commit is contained in:
Ryan Fleury
2025-04-10 14:29:57 -07:00
parent cde079a14d
commit fbe747a8b4
13 changed files with 476 additions and 601 deletions
-39
View File
@@ -581,45 +581,6 @@ struct E_LookupRuleExprPair
};
#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))
typedef E_IRGEN_FUNCTION_SIG(E_IRGenFunctionType);
E_IRGEN_FUNCTION_DEF(default);
typedef struct E_IRGenRule E_IRGenRule;
struct E_IRGenRule
{
String8 name;
E_IRGenFunctionType *irgen;
};
typedef struct E_IRGenRuleNode E_IRGenRuleNode;
struct E_IRGenRuleNode
{
E_IRGenRuleNode *next;
E_IRGenRule v;
};
typedef struct E_IRGenRuleSlot E_IRGenRuleSlot;
struct E_IRGenRuleSlot
{
E_IRGenRuleNode *first;
E_IRGenRuleNode *last;
};
typedef struct E_IRGenRuleMap E_IRGenRuleMap;
struct E_IRGenRuleMap
{
U64 slots_count;
E_IRGenRuleSlot *slots;
};
#endif
////////////////////////////////
//~ rjf: Type Pattern -> Hook Key Data Structure (Auto View Rules)
+41 -237
View File
@@ -699,150 +699,6 @@ E_LOOKUP_RANGE_FUNCTION_DEF(only_and_omit)
}
#endif
////////////////////////////////
//~ rjf: Lookups
#if 0 // TODO(rjf): @eval
internal E_LookupRuleMap
e_lookup_rule_map_make(Arena *arena, U64 slots_count)
{
E_LookupRuleMap map = {0};
map.slots_count = slots_count;
map.slots = push_array(arena, E_LookupRuleSlot, map.slots_count);
e_lookup_rule_map_insert_new(arena, &map, str8_lit("default"),
.info = E_LOOKUP_INFO_FUNCTION_NAME(default),
.range = E_LOOKUP_RANGE_FUNCTION_NAME(default),
.id_from_num = E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(default),
.num_from_id = E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(default));
e_lookup_rule_map_insert_new(arena, &map, str8_lit("folder"),
.info = E_LOOKUP_INFO_FUNCTION_NAME(folder),
.range = E_LOOKUP_RANGE_FUNCTION_NAME(folder),
.id_from_num = E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(folder),
.num_from_id = E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(folder));
e_lookup_rule_map_insert_new(arena, &map, str8_lit("file"),
.info = E_LOOKUP_INFO_FUNCTION_NAME(file),
.access = E_LOOKUP_ACCESS_FUNCTION_NAME(file),
.range = E_LOOKUP_RANGE_FUNCTION_NAME(file));
e_lookup_rule_map_insert_new(arena, &map, str8_lit("slice"),
.info = E_LOOKUP_INFO_FUNCTION_NAME(slice),
.range = E_LOOKUP_RANGE_FUNCTION_NAME(slice));
e_lookup_rule_map_insert_new(arena, &map, str8_lit("only"),
.info = E_LOOKUP_INFO_FUNCTION_NAME(only),
.range = E_LOOKUP_RANGE_FUNCTION_NAME(only_and_omit));
e_lookup_rule_map_insert_new(arena, &map, str8_lit("omit"),
.info = E_LOOKUP_INFO_FUNCTION_NAME(omit),
.range = E_LOOKUP_RANGE_FUNCTION_NAME(only_and_omit));
return map;
}
internal void
e_lookup_rule_map_insert(Arena *arena, E_LookupRuleMap *map, E_LookupRule *rule)
{
U64 hash = e_hash_from_string(5381, rule->name);
U64 slot_idx = hash%map->slots_count;
E_LookupRuleNode *n = push_array(arena, E_LookupRuleNode, 1);
SLLQueuePush(map->slots[slot_idx].first, map->slots[slot_idx].last, n);
MemoryCopyStruct(&n->v, rule);
if(n->v.info == 0) { n->v.info = E_LOOKUP_INFO_FUNCTION_NAME(default); }
if(n->v.access == 0) { n->v.access = E_LOOKUP_ACCESS_FUNCTION_NAME(default); }
if(n->v.range == 0) { n->v.range = E_LOOKUP_RANGE_FUNCTION_NAME(default); }
if(n->v.id_from_num == 0){ n->v.id_from_num = E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(default); }
if(n->v.num_from_id == 0){ n->v.num_from_id = E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(default); }
n->v.name = push_str8_copy(arena, n->v.name);
}
internal E_LookupRule *
e_lookup_rule_from_string(String8 string)
{
E_LookupRule *result = &e_lookup_rule__nil;
if(e_ir_state->ctx->lookup_rule_map != 0 && e_ir_state->ctx->lookup_rule_map->slots_count != 0)
{
U64 hash = e_hash_from_string(5381, string);
U64 slot_idx = hash%e_ir_state->ctx->lookup_rule_map->slots_count;
for(E_LookupRuleNode *n = e_ir_state->ctx->lookup_rule_map->slots[slot_idx].first;
n != 0;
n = n->next)
{
if(str8_match(n->v.name, string, 0))
{
result = &n->v;
break;
}
}
}
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);
E_IRNode *root = e_push_irnode(arena, RDI_EvalOp_ByteSwap);
e_irnode_push_child(root, irtree.root);
E_IRTreeAndType result = {root, irtree.type_key, irtree.mode, irtree.msgs};
return result;
}
E_IRGEN_FUNCTION_DEF(array)
{
E_Expr *ptr_expr = expr->first->next;
E_Expr *count_expr = ptr_expr->next;
E_IRTreeAndType result = e_irtree_and_type_from_expr(arena, ptr_expr);
E_TypeKey element_type_key = e_type_ptee_from_key(result.type_key);
E_Value count_value = e_value_from_expr(count_expr);
result.type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, element_type_key, count_value.u64, 0);
return result;
}
internal E_IRGenRuleMap
e_irgen_rule_map_make(Arena *arena, U64 slots_count)
{
E_IRGenRuleMap map = {0};
map.slots_count = slots_count;
map.slots = push_array(arena, E_IRGenRuleSlot, map.slots_count);
e_irgen_rule_map_insert_new(arena, &map, str8_lit("default"), .irgen = E_IRGEN_FUNCTION_NAME(default));
e_irgen_rule_map_insert_new(arena, &map, str8_lit("bswap"), .irgen = E_IRGEN_FUNCTION_NAME(bswap));
e_irgen_rule_map_insert_new(arena, &map, str8_lit("array"), .irgen = E_IRGEN_FUNCTION_NAME(array));
return map;
}
internal void
e_irgen_rule_map_insert(Arena *arena, E_IRGenRuleMap *map, E_IRGenRule *rule)
{
U64 hash = e_hash_from_string(5381, rule->name);
U64 slot_idx = hash%map->slots_count;
E_IRGenRuleNode *n = push_array(arena, E_IRGenRuleNode, 1);
MemoryCopyStruct(&n->v, rule);
n->v.name = push_str8_copy(arena, n->v.name);
SLLQueuePush(map->slots[slot_idx].first, map->slots[slot_idx].last, n);
}
internal E_IRGenRule *
e_irgen_rule_from_string(String8 string)
{
E_IRGenRule *rule = &e_irgen_rule__default;
if(e_ir_state != 0 && e_ir_state->ctx != 0 && e_ir_state->ctx->irgen_rule_map != 0 && e_ir_state->ctx->irgen_rule_map->slots_count != 0)
{
E_IRGenRuleMap *map = e_ir_state->ctx->irgen_rule_map;
U64 hash = e_hash_from_string(5381, string);
U64 slot_idx = hash%map->slots_count;
for(E_IRGenRuleNode *n = map->slots[slot_idx].first; n != 0; n = n->next)
{
if(str8_match(string, n->v.name, 0))
{
rule = &n->v;
break;
}
}
}
return rule;
}
#endif
////////////////////////////////
//~ rjf: Auto Hooks
@@ -1658,8 +1514,47 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
{
default:{}break;
//- rjf: accesses
//- rjf: member accesses
case E_ExprKind_MemberAccess:
{
// rjf: unpack left-hand-size
E_Expr *lhs = expr->first;
E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs);
// rjf: if the right-hand-side is a call, then this is short-hand for
// the right-hand-side call, with the left-hand-side as the first argument.
E_Expr *rhs = lhs->next;
if(rhs->kind == E_ExprKind_Call)
{
E_Expr *rhs_copy = e_expr_copy(arena, rhs);
e_expr_insert_child(rhs_copy, rhs_copy->first, e_expr_ref(arena, lhs));
result = e_irtree_and_type_from_expr(arena, rhs_copy);
}
// rjf: if the right-hand-side is a leaf identifier, then this is an
// "access" to the left-hand-side.
else if(rhs->kind == E_ExprKind_LeafIdentifier)
{
// 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);
}
// rjf: if the right-hand-side is anything else, this is an invalid formation.
else
{
e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Expected identifier or call after `.`.");
}
}break;
//- rjf: array indices
case E_ExprKind_ArrayIndex:
{
// rjf: unpack left-hand-size
@@ -1686,7 +1581,7 @@ e_irtree_and_type_from_expr(Arena *arena, E_Expr *root_expr)
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);
E_TypeKey r_type_direct = e_type_unwrap(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);
@@ -3181,94 +3076,3 @@ e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_Type
e_expr_push_child(root, rhs_bytecode);
return root;
}
////////////////////////////////
//~ rjf: Expression & IR-Tree => Rules
#if 0 // TODO(rjf): @eval
internal E_LookupRule *
e_lookup_rule_from_type_key(E_TypeKey type_key)
{
E_LookupRule *rule = &e_lookup_rule__default;
// rjf: unpack type
E_Type *type = e_type_from_key__cached(type_key);
// rjf: sets / lenses -> try to implicitly map to a rule based on name
if(type->kind == E_TypeKind_Set || type->kind == E_TypeKind_Lens)
{
E_LookupRule *candidate = e_lookup_rule_from_string(type->name);
if(candidate != &e_lookup_rule__nil)
{
rule = candidate;
}
}
return rule;
}
#endif
#if 0 // TODO(rjf): @eval
internal E_LookupRuleExprPair
e_lookup_rule_tag_pair_from_expr_irtree(E_Expr *expr, E_IRTreeAndType *irtree)
{
E_LookupRuleExprPair result = {&e_lookup_rule__default, &e_expr_nil};
{
// rjf: first try explicitly-stored tags
B32 default_is_forced = 0;
if(result.rule == &e_lookup_rule__default)
{
for(E_Expr *tag = expr->first_tag; tag != &e_expr_nil; tag = tag->next)
{
if(e_expr_is_poisoned(tag)) { continue; }
if(str8_match(tag->string, e_lookup_rule__default.name, 0))
{
result.rule = &e_lookup_rule__default;
result.tag = &e_expr_nil;
default_is_forced = 1;
break;
}
E_LookupRule *candidate = e_lookup_rule_from_string(tag->string);
if(candidate != &e_lookup_rule__nil)
{
result.rule = candidate;
result.tag = tag;
}
}
}
// rjf: next try implicit set name -> rule mapping
if(!default_is_forced && result.rule == &e_lookup_rule__default)
{
E_TypeKind type_kind = e_type_kind_from_key(irtree->type_key);
if(type_kind == E_TypeKind_Stub)
{
E_Type *type = e_type_from_key__cached(irtree->type_key);
String8 name = type->name;
E_LookupRule *candidate = e_lookup_rule_from_string(name);
if(candidate != &e_lookup_rule__nil)
{
result.rule = candidate;
}
}
}
// rjf: next try auto hook map
if(!default_is_forced && result.rule == &e_lookup_rule__default)
{
E_ExprList tags = e_auto_hook_exprs_from_type_key__cached(irtree->type_key);
for(E_ExprNode *n = tags.first; n != 0; n = n->next)
{
if(e_expr_is_poisoned(n->v)) { continue; }
E_LookupRule *candidate = e_lookup_rule_from_string(n->v->string);
if(candidate != &e_lookup_rule__nil)
{
result.rule = candidate;
result.tag = n->v;
}
}
}
}
return result;
}
#endif
-63
View File
@@ -134,10 +134,6 @@ 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;
};
@@ -166,32 +162,6 @@ struct E_IRState
////////////////////////////////
//~ rjf: Globals
#if 0 // TODO(rjf): @eval
local_persist read_only E_LookupRule e_lookup_rule__nil =
{
str8_lit_comp("nil"),
E_LOOKUP_INFO_FUNCTION_NAME(default),
E_LOOKUP_ACCESS_FUNCTION_NAME(default),
E_LOOKUP_RANGE_FUNCTION_NAME(default),
E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(default),
E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(default),
};
local_persist read_only E_LookupRule e_lookup_rule__default =
{
str8_lit_comp("default"),
E_LOOKUP_INFO_FUNCTION_NAME(default),
E_LOOKUP_ACCESS_FUNCTION_NAME(default),
E_LOOKUP_RANGE_FUNCTION_NAME(default),
E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(default),
E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(default),
};
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;
@@ -206,28 +176,6 @@ internal B32 e_expr_kind_is_comparison(E_ExprKind kind);
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
@@ -294,15 +242,4 @@ internal E_Expr *e_expr_irext_array_index(Arena *arena, E_Expr *lhs, E_IRTreeAnd
internal E_Expr *e_expr_irext_deref(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree);
internal E_Expr *e_expr_irext_cast(Arena *arena, E_Expr *rhs, E_IRTreeAndType *rhs_irtree, E_TypeKey type_key);
////////////////////////////////
//~ 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);
#endif
#endif // EVAL_IR_H
+22 -32
View File
@@ -1208,7 +1208,8 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray tok
B32 is_postfix_unary = 0;
// rjf: dot/arrow operator
if(token.kind == E_TokenKind_Symbol &&
if(max_precedence >= 1 &&
token.kind == E_TokenKind_Symbol &&
(str8_match(token_string, str8_lit("."), 0) ||
str8_match(token_string, str8_lit("->"), 0)))
{
@@ -1217,43 +1218,29 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray tok
// rjf: advance past operator
it += 1;
// rjf: expect member name
String8 member_name = {0};
B32 good_member_name = 0;
{
E_Token member_name_maybe = e_token_at_it(it, &tokens);
String8 member_name_maybe_string = str8_substr(text, member_name_maybe.range);
if(member_name_maybe.kind != E_TokenKind_Identifier)
{
e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token_string.str, "Expected member name after `%S`.", token_string);
}
else
{
member_name = member_name_maybe_string;
good_member_name = 1;
}
}
// rjf: parse right-hand-side
E_Parse rhs_expr_parse = e_parse_expr_from_text_tokens__prec(arena, text, e_token_array_make_first_opl(it, it_opl), 0, 1);
e_msg_list_concat_in_place(&result.msgs, &rhs_expr_parse.msgs);
E_Expr *rhs = rhs_expr_parse.exprs.last;
it = rhs_expr_parse.last_token;
// rjf: produce lookup member expr
if(good_member_name)
// rjf: produce member access expr
if(rhs == &e_expr_nil)
{
E_Expr *member_container = atom;
E_Expr *member_expr = e_push_expr(arena, E_ExprKind_LeafIdentifier, member_name.str);
member_expr->string = member_name;
e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token_string.str, "Missing right-hand-side of `.`.");
}
else
{
E_Expr *lhs = atom;
atom = e_push_expr(arena, E_ExprKind_MemberAccess, token_string.str);
e_expr_push_child(atom, member_container);
e_expr_push_child(atom, member_expr);
}
// rjf: increment past good member names
if(good_member_name)
{
it += 1;
e_expr_push_child(atom, lhs);
e_expr_push_child(atom, rhs);
}
}
// rjf: array index
if(token.kind == E_TokenKind_Symbol &&
if(max_precedence >= 1 &&
token.kind == E_TokenKind_Symbol &&
str8_match(token_string, str8_lit("["), 0))
{
is_postfix_unary = 1;
@@ -1292,9 +1279,12 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray tok
}
// rjf: calls
if(token.kind == E_TokenKind_Symbol &&
if(max_precedence >= 0 &&
token.kind == E_TokenKind_Symbol &&
str8_match(token_string, str8_lit("("), 0))
{
is_postfix_unary = 1;
// rjf: skip (
it += 1;
+13 -11
View File
@@ -348,7 +348,8 @@ e_hash_from_cons_type_params(E_ConsTypeParams *params)
internal B32
e_cons_type_params_match(E_ConsTypeParams *l, E_ConsTypeParams *r)
{
B32 result = (l->kind == r->kind &&
B32 result = (l->kind != E_TypeKind_Lens &&
l->kind == r->kind &&
l->flags == r->flags &&
str8_match(l->name, r->name, 0) &&
e_type_key_match(l->direct_key, r->direct_key) &&
@@ -1665,7 +1666,7 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
default:
{
E_Type *type = e_type_from_key__cached(key);
str8_list_push(arena, out, push_str8_copy(arena, type->name));
str8_list_pushf(arena, out, "%S ", type->name);
}break;
case E_TypeKind_Bitfield:
@@ -1702,7 +1703,7 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
case E_TypeKind_Alias:
{
E_Type *type = e_type_from_key__cached(key);
str8_list_push(arena, out, push_str8_copy(arena, type->name));
str8_list_pushf(arena, out, "%S ", type->name);
}break;
case E_TypeKind_IncompleteStruct: keyword = str8_lit("struct"); goto fwd_udt;
@@ -1714,7 +1715,7 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
E_Type *type = e_type_from_key__cached(key);
str8_list_push(arena, out, keyword);
str8_list_push(arena, out, str8_lit(" "));
str8_list_push(arena, out, push_str8_copy(arena, type->name));
str8_list_pushf(arena, out, "%S ", type->name);
}break;
case E_TypeKind_Array:
@@ -1753,20 +1754,15 @@ e_type_lhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
str8_list_pushf(arena, out, ", ");
}
}
str8_list_pushf(arena, out, ") <- (");
str8_list_pushf(arena, out, ") <- ");
E_TypeKey direct = e_type_direct_from_key(key);
e_type_lhs_string_from_key(arena, direct, out, 1, skip_return);
str8_list_pushf(arena, out, ")");
e_type_lhs_string_from_key(arena, direct, out, 2, skip_return);
}break;
case E_TypeKind_Ptr:
{
E_TypeKey direct = e_type_direct_from_key(key);
e_type_lhs_string_from_key(arena, direct, out, 1, skip_return);
if(!e_type_kind_is_pointer_or_ref(e_type_kind_from_key(direct)))
{
str8_list_push(arena, out, str8_lit(" "));
}
str8_list_push(arena, out, str8_lit("*"));
E_Type *type = e_type_from_key__cached(key);
if(type->count != 1)
@@ -1879,6 +1875,12 @@ e_type_rhs_string_from_key(Arena *arena, E_TypeKey key, String8List *out, U32 pr
E_TypeKey direct = e_type_direct_from_key(key);
e_type_rhs_string_from_key(arena, direct, out, 2);
}break;
case E_TypeKind_Lens:
if(prec == 1)
{
str8_list_push(arena, out, str8_lit(")"));
}break;
}
}