eval: specify formal way in which tags (view rules) can fit into expression language, both in parsing & in structure; introduce ir-generation hook step in eval pipeline, transfer most of the default non-vbisualization view rule features to that layer

This commit is contained in:
Ryan Fleury
2025-02-01 20:50:31 -08:00
parent aac93b5952
commit 07c9268941
7 changed files with 536 additions and 54 deletions
+4
View File
@@ -117,6 +117,8 @@ E_ExprKindTable:
{ Ternary Null 0 "? " "" "?" ":"}
{ Call Null 0 "()" "(" "," ")"}
{ LeafBytecode Null 0 "bytecode" "" "" "" }
{ LeafMember Null 0 "member" "" "" "" }
{ LeafStringLiteral Null 0 "string_literal" "" "" "" }
@@ -136,6 +138,8 @@ E_ExprKindTable:
{ Line Binary 1 ":" "" ":" "" }
{ Define Binary 13 "=" "" "=" "" }
{ Tag Null 0 "=>" "=>" "," "" }
}
@table(name display_string)
+276 -42
View File
@@ -455,6 +455,196 @@ E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(default)
return id;
}
////////////////////////////////
//~ rjf: IR Gen Rules
E_IRGEN_FUNCTION_DEF(cast)
{
E_Expr *type_expr = tag->first->next;
E_TypeKey type_key = e_type_from_expr(type_expr);
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr);
E_IRTreeAndType result = {irtree.root, type_key, irtree.mode, irtree.msgs};
return result;
}
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_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr);
E_TypeKey type_key = irtree.type_key;
E_TypeKind type_kind = e_type_kind_from_key(type_key);
if(e_type_kind_is_pointer_or_ref(type_kind))
{
Temp scratch = scratch_begin(&arena, 1);
E_Eval count_eval = e_eval_from_expr(scratch.arena, tag->first->next);
E_TypeKey element_type_key = e_type_ptee_from_key(type_key);
E_TypeKey array_type_key = e_type_key_cons_array(element_type_key, count_eval.value.u64);
E_TypeKey ptr_type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, array_type_key, 0);
irtree.type_key = ptr_type_key;
scratch_end(scratch);
}
return irtree;
}
E_IRGEN_FUNCTION_DEF(slice)
{
Temp scratch = scratch_begin(&arena, 1);
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr);
E_TypeKind type_kind = e_type_kind_from_key(irtree.type_key);
if(type_kind == E_TypeKind_Struct || type_kind == E_TypeKind_Class)
{
// rjf: unpack members
E_MemberArray members = e_type_data_members_from_key__cached(irtree.type_key);
// rjf: choose base pointer & count members
E_Member *base_ptr_member = 0;
E_Member *count_member = 0;
for(U64 idx = 0; idx < members.count; idx += 1)
{
E_Member *member = &members.v[idx];
E_TypeKey member_type = e_type_unwrap(member->type_key);
E_TypeKind member_type_kind = e_type_kind_from_key(member_type);
if(count_member == 0 && e_type_kind_is_integer(member_type_kind))
{
count_member = member;
}
if(base_ptr_member == 0 && e_type_kind_is_pointer_or_ref(member_type_kind))
{
base_ptr_member = &members.v[idx];
}
if(count_member != 0 && base_ptr_member != 0)
{
break;
}
}
// rjf: evaluate count member, determine count
U64 count = 0;
if(count_member != 0)
{
E_Expr *count_member_expr = e_expr_ref_member_access(scratch.arena, expr, count_member->name);
E_Eval count_member_eval = e_eval_from_expr(scratch.arena, count_member_expr);
E_Eval count_member_value_eval = e_value_eval_from_eval(count_member_eval);
count = count_member_value_eval.value.u64;
}
// rjf: generate new struct slice type
E_TypeKey slice_type_key = zero_struct;
if(base_ptr_member != 0 && count_member != 0)
{
String8 struct_name = e_type_string_from_key(scratch.arena, irtree.type_key);
E_TypeKey element_type_key = e_type_ptee_from_key(base_ptr_member->type_key);
E_TypeKey array_type_key = e_type_key_cons_array(element_type_key, count);
E_TypeKey sized_base_ptr_type_key = e_type_key_cons_ptr(e_type_state->ctx->primary_module->arch, array_type_key, 0);
E_MemberList slice_type_members = {0};
e_member_list_push(scratch.arena, &slice_type_members, count_member);
e_member_list_push(scratch.arena, &slice_type_members, &(E_Member){.kind = E_MemberKind_DataField, .type_key = sized_base_ptr_type_key, .name = base_ptr_member->name, .pretty_name = base_ptr_member->pretty_name, .off = base_ptr_member->off});
E_MemberArray slice_type_members_array = e_member_array_from_list(scratch.arena, &slice_type_members);
slice_type_key = e_type_key_cons(.arch = e_type_state->ctx->primary_module->arch,
.kind = E_TypeKind_Struct,
.name = struct_name,
.members = slice_type_members_array.v,
.count = slice_type_members_array.count);
}
// rjf: overwrite type
irtree.type_key = slice_type_key;
}
scratch_end(scratch);
return irtree;
}
E_IRGEN_FUNCTION_DEF(wrap)
{
Temp scratch = scratch_begin(&arena, 1);
E_Expr *expr_to_irify = expr;
E_Expr *wrap_expr_src = tag->first->next;
if(wrap_expr_src != &e_expr_nil)
{
expr_to_irify = e_expr_copy(scratch.arena, wrap_expr_src);
typedef struct Task Task;
struct Task
{
Task *next;
E_Expr *parent;
E_Expr *expr;
};
Task start_task = {0, &e_expr_nil, expr_to_irify};
Task *first_task = &start_task;
Task *last_task = first_task;
for(Task *t = first_task; t != 0; t = t->next)
{
if(t->expr->kind == E_ExprKind_LeafIdent && str8_match(t->expr->string, str8_lit("$expr"), 0))
{
E_Expr *original_expr_ref = e_expr_ref(arena, expr);
if(t->parent != &e_expr_nil)
{
e_expr_insert_child(t->parent, t->expr, original_expr_ref);
e_expr_remove_child(t->parent, t->expr);
}
}
else for(E_Expr *child = t->expr->first; child != &e_expr_nil; child = child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
SLLQueuePush(first_task, last_task, task);
task->parent = t->expr;
task->expr = child;
}
}
}
E_IRTreeAndType irtree = e_irtree_and_type_from_expr(arena, expr_to_irify);
scratch_end(scratch);
return irtree;
}
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);
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;
{
E_IRGenRuleMap *map = e_ir_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;
}
////////////////////////////////
//~ rjf: IR-ization Functions
@@ -752,8 +942,7 @@ e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_Type
//- rjf: top-level irtree/type extraction
internal E_IRTreeAndType
e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr *expr)
E_IRGEN_FUNCTION_DEF(default)
{
E_IRTreeAndType result = {&e_irnode_nil};
E_ExprKind kind = expr->kind;
@@ -764,7 +953,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
//- rjf: references -> just descend to sub-expr
case E_ExprKind_Ref:
{
result = e_irtree_and_type_from_expr__space(arena, current_space, expr->ref);
result = e_irtree_and_type_from_expr(arena, expr->ref);
}break;
//- rjf: accesses
@@ -793,7 +982,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr__space(arena, current_space, r_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);
@@ -848,7 +1037,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr__space(arena, current_space, r_expr);
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr);
E_TypeKey r_type = r_tree.type_key;
E_TypeKey r_type_unwrapped = e_type_unwrap(r_type);
E_TypeKind r_type_unwrapped_kind = e_type_kind_from_key(r_type_unwrapped);
@@ -879,7 +1068,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
E_TypeKey cast_type = e_type_from_expr(cast_type_expr);
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);
E_IRTreeAndType casted_tree = e_irtree_and_type_from_expr__space(arena, current_space, casted_expr);
E_IRTreeAndType casted_tree = e_irtree_and_type_from_expr(arena, casted_expr);
e_msg_list_concat_in_place(&result.msgs, &casted_tree.msgs);
E_TypeKey casted_type = e_type_unwrap(casted_tree.type_key);
E_TypeKind casted_type_kind = e_type_kind_from_key(casted_type);
@@ -945,7 +1134,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
}break;
default:
{
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr__space(arena, current_space, r_expr);
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
r_type = r_tree.type_key;
}break;
@@ -975,7 +1164,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
{
// rjf: evaluate operand tree
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr__space(arena, current_space, r_expr);
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
// rjf: fill output
@@ -989,7 +1178,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr__space(arena, current_space, r_expr);
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
E_TypeKey r_type = e_type_unwrap(r_tree.type_key);
E_TypeKind r_type_kind = e_type_kind_from_key(r_type);
@@ -1017,7 +1206,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
//- rjf: unary operations
case E_ExprKind_Pos:
{
result = e_irtree_and_type_from_expr__space(arena, current_space, expr->first);
result = e_irtree_and_type_from_expr(arena, expr->first);
}break;
case E_ExprKind_Neg:
case E_ExprKind_LogNot:
@@ -1025,7 +1214,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
{
// rjf: unpack operand
E_Expr *r_expr = expr->first;
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr__space(arena, current_space, r_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);
RDI_EvalTypeGroup r_type_group = e_type_group_from_kind(r_type_kind);
@@ -1080,8 +1269,8 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
B32 is_comparison = e_expr_kind_is_comparison(kind);
E_Expr *l_expr = expr->first;
E_Expr *r_expr = l_expr->next;
E_IRTreeAndType l_tree = e_irtree_and_type_from_expr__space(arena, current_space, l_expr);
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr__space(arena, current_space, r_expr);
E_IRTreeAndType l_tree = e_irtree_and_type_from_expr(arena, l_expr);
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr);
e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
E_TypeKey l_type = e_type_unwrap_enum(e_type_unwrap(l_tree.type_key));
@@ -1304,9 +1493,9 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
E_Expr *c_expr = expr->first;
E_Expr *l_expr = c_expr->next;
E_Expr *r_expr = l_expr->next;
E_IRTreeAndType c_tree = e_irtree_and_type_from_expr__space(arena, current_space, c_expr);
E_IRTreeAndType l_tree = e_irtree_and_type_from_expr__space(arena, current_space, l_expr);
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr__space(arena, current_space, r_expr);
E_IRTreeAndType c_tree = e_irtree_and_type_from_expr(arena, c_expr);
E_IRTreeAndType l_tree = e_irtree_and_type_from_expr(arena, l_expr);
E_IRTreeAndType r_tree = e_irtree_and_type_from_expr(arena, r_expr);
e_msg_list_concat_in_place(&result.msgs, &c_tree.msgs);
e_msg_list_concat_in_place(&result.msgs, &l_tree.msgs);
e_msg_list_concat_in_place(&result.msgs, &r_tree.msgs);
@@ -1350,6 +1539,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
case E_ExprKind_LeafBytecode:
{
E_IRNode *new_tree = e_irtree_bytecode_no_copy(arena, expr->bytecode);
new_tree->space = expr->space;
E_TypeKey final_type_key = expr->type_key;
result.root = new_tree;
result.type_key = final_type_key;
@@ -1427,7 +1617,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
else
{
e_string2expr_map_inc_poison(e_ir_ctx->macro_map, expr->string);
result = e_irtree_and_type_from_expr__space(arena, current_space, macro_expr);
result = e_irtree_and_type_from_expr(arena, macro_expr);
e_string2expr_map_dec_poison(e_ir_ctx->macro_map, expr->string);
}
}break;
@@ -1437,6 +1627,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
{
E_IRNode *new_tree = e_push_irnode(arena, RDI_EvalOp_ConstU64);
new_tree->value.u64 = expr->value.u64;
new_tree->space = expr->space;
result.root = new_tree;
result.type_key = expr->type_key;
result.mode = E_Mode_Offset;
@@ -1449,8 +1640,8 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
E_Space space = {E_SpaceKind_HashStoreKey, .u128 = key};
U64 size = fs_size_from_path(expr->string);
E_IRNode *base_offset = e_irtree_const_u(arena, 0);
E_IRNode *set_space = e_irtree_set_space(arena, space, base_offset);
result.root = set_space;
base_offset->space = space;
result.root = base_offset;
result.type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), size);
result.mode = E_Mode_Offset;
}break;
@@ -1459,6 +1650,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
case E_ExprKind_TypeIdent:
{
result.root = e_irtree_const_u(arena, 0);
result.root->space = expr->space;
result.type_key = expr->type_key;
result.mode = E_Mode_Null;
}break;
@@ -1476,7 +1668,7 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
{
E_Expr *lhs = expr->first;
E_Expr *rhs = expr->last;
E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr__space(arena, current_space, lhs);
E_IRTreeAndType lhs_irtree = e_irtree_and_type_from_expr(arena, lhs);
U64 line_num = rhs->value.u64;
B32 space_is_good = 1;
E_Space space = {0};
@@ -1506,10 +1698,10 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
Rng1U64 line_range = text_info.lines_ranges[line_num-1];
U64 line_size = dim_1u64(line_range);
E_IRNode *line_offset = e_irtree_const_u(arena, line_range.min);
E_IRNode *set_space = e_irtree_set_space(arena, space, line_offset);
result.root = set_space;
result.type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), line_size);
result.mode = E_Mode_Offset;
result.root = line_offset;
result.root->space = space;
result.type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), line_size);
result.mode = E_Mode_Offset;
}
else
{
@@ -1524,41 +1716,82 @@ e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr
{
E_Expr *lhs = expr->first;
E_Expr *rhs = lhs->next;
result = e_irtree_and_type_from_expr__space(arena, current_space, rhs);
result = e_irtree_and_type_from_expr(arena, rhs);
if(lhs->kind != E_ExprKind_LeafIdent)
{
e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, expr->location, "Left side of assignment must be an unused identifier.");
}
}break;
}
//- rjf: if the expression's space does not match the current, then push a set-space node
// before returning
E_Space zero_space = zero_struct;
if(!MemoryMatchStruct(current_space, &expr->space) &&
!MemoryMatchStruct(&zero_space, &expr->space))
{
result.root = e_irtree_set_space(arena, expr->space, result.root);
*current_space = expr->space;
}
return result;
}
internal E_IRTreeAndType
e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr)
{
E_Space space = e_interpret_ctx->primary_space;
E_IRTreeAndType result = e_irtree_and_type_from_expr__space(arena, &space, expr);
E_IRTreeAndType result = {&e_irnode_nil};
E_IRGenRule *irgen_rule = &e_irgen_rule__default;
E_Expr *irgen_rule_tag = &e_expr_nil;
for(E_Expr *tag = expr->first_tag; tag != &e_expr_nil; tag = tag->next)
{
String8 name = tag->first->string;
E_IRGenRule *irgen_rule_candidate = e_irgen_rule_from_string(name);
if(irgen_rule_candidate != &e_irgen_rule__default)
{
B32 tag_is_poisoned = 0;
U64 hash = e_hash_from_string(5381, str8_struct(&tag));
U64 slot_idx = hash%e_ir_ctx->used_tag_map->slots_count;
for(E_UsedTagNode *n = e_ir_ctx->used_tag_map->slots[slot_idx].first; n != 0; n = n->next)
{
if(n->tag == tag)
{
tag_is_poisoned = 1;
break;
}
}
if(!tag_is_poisoned)
{
E_UsedTagNode *n = push_array(arena, E_UsedTagNode, 1);
n->tag = tag;
DLLPushBack(e_ir_ctx->used_tag_map->slots[slot_idx].first, e_ir_ctx->used_tag_map->slots[slot_idx].last, n);
irgen_rule_tag = tag;
irgen_rule = irgen_rule_candidate;
break;
}
}
}
result = irgen_rule->irgen(arena, expr, irgen_rule_tag);
if(irgen_rule_tag != &e_expr_nil)
{
U64 hash = e_hash_from_string(5381, str8_struct(&irgen_rule_tag));
U64 slot_idx = hash%e_ir_ctx->used_tag_map->slots_count;
for(E_UsedTagNode *n = e_ir_ctx->used_tag_map->slots[slot_idx].first; n != 0; n = n->next)
{
if(n->tag == irgen_rule_tag)
{
DLLRemove(e_ir_ctx->used_tag_map->slots[slot_idx].first, e_ir_ctx->used_tag_map->slots[slot_idx].last, n);
break;
}
}
}
return result;
}
//- rjf: irtree -> linear ops/bytecode
internal void
e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out)
e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out)
{
U32 op = root->op;
{
E_Space zero_space = zero_struct;
if(!MemoryMatchStruct(&root->space, &zero_space) &&
!MemoryMatchStruct(&root->space, current_space))
{
*current_space = root->space;
e_oplist_push_set_space(arena, out, root->space);
}
}
switch(op)
{
case RDI_EvalOp_Stop:
@@ -1581,7 +1814,7 @@ e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out)
child != &e_irnode_nil;
child = child->next)
{
e_append_oplist_from_irtree(arena, child, out);
e_append_oplist_from_irtree(arena, child, current_space, out);
}
}break;
@@ -1632,7 +1865,7 @@ e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out)
child != &e_irnode_nil && idx < child_count;
child = child->next, idx += 1)
{
e_append_oplist_from_irtree(arena, child, out);
e_append_oplist_from_irtree(arena, child, current_space, out);
}
// rjf: emit op to compute this node
@@ -1646,7 +1879,8 @@ internal E_OpList
e_oplist_from_irtree(Arena *arena, E_IRNode *root)
{
E_OpList ops = {0};
e_append_oplist_from_irtree(arena, root, &ops);
E_Space space = e_interpret_ctx->primary_space;
e_append_oplist_from_irtree(arena, root, &space, &ops);
return ops;
}
+84 -7
View File
@@ -42,6 +42,7 @@ struct E_IRNode
E_IRNode *last;
E_IRNode *next;
RDI_EvalOp op;
E_Space space;
String8 string;
E_Value value;
};
@@ -84,31 +85,30 @@ struct E_LookupRange
#define E_LOOKUP_INFO_FUNCTION_NAME(name) e_lookup_info_##name
#define E_LOOKUP_INFO_FUNCTION_DEF(name) internal E_LOOKUP_INFO_FUNCTION_SIG(E_LOOKUP_INFO_FUNCTION_NAME(name))
typedef E_LOOKUP_INFO_FUNCTION_SIG(E_LookupInfoFunctionType);
E_LOOKUP_INFO_FUNCTION_DEF(default);
#define E_LOOKUP_ACCESS_FUNCTION_SIG(name) E_LookupAccess name(Arena *arena, E_ExprKind kind, E_Expr *lhs, E_Expr *rhs, void *user_data)
#define E_LOOKUP_ACCESS_FUNCTION_NAME(name) e_lookup_access_##name
#define E_LOOKUP_ACCESS_FUNCTION_DEF(name) internal E_LOOKUP_ACCESS_FUNCTION_SIG(E_LOOKUP_ACCESS_FUNCTION_NAME(name))
typedef E_LOOKUP_ACCESS_FUNCTION_SIG(E_LookupAccessFunctionType);
E_LOOKUP_ACCESS_FUNCTION_DEF(default);
#define E_LOOKUP_RANGE_FUNCTION_SIG(name) E_LookupRange name(Arena *arena, E_Expr *lhs, Rng1U64 idx_range, void *user_data)
#define E_LOOKUP_RANGE_FUNCTION_NAME(name) e_lookup_range_##name
#define E_LOOKUP_RANGE_FUNCTION_DEF(name) internal E_LOOKUP_RANGE_FUNCTION_SIG(E_LOOKUP_RANGE_FUNCTION_NAME(name))
typedef E_LOOKUP_RANGE_FUNCTION_SIG(E_LookupRangeFunctionType);
E_LOOKUP_RANGE_FUNCTION_DEF(default);
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(name) U64 name(U64 num, void *user_data)
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(name) e_lookup_id_from_num_##name
#define E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(name) internal E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(E_LOOKUP_ID_FROM_NUM_FUNCTION_NAME(name))
typedef E_LOOKUP_ID_FROM_NUM_FUNCTION_SIG(E_LookupIDFromNumFunctionType);
E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(default);
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(name) U64 name(U64 id, void *user_data)
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(name) e_lookup_num_from_id_##name
#define E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(name) internal E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(E_LOOKUP_NUM_FROM_ID_FUNCTION_NAME(name))
typedef E_LOOKUP_NUM_FROM_ID_FUNCTION_SIG(E_LookupNumFromIDFunctionType);
E_LOOKUP_INFO_FUNCTION_DEF(default);
E_LOOKUP_ACCESS_FUNCTION_DEF(default);
E_LOOKUP_RANGE_FUNCTION_DEF(default);
E_LOOKUP_ID_FROM_NUM_FUNCTION_DEF(default);
E_LOOKUP_NUM_FROM_ID_FUNCTION_DEF(default);
typedef struct E_LookupRule E_LookupRule;
@@ -143,6 +143,68 @@ struct E_LookupRuleMap
U64 slots_count;
};
////////////////////////////////
//~ rjf: IR Generation Hooks
#define E_IRGEN_FUNCTION_SIG(name) E_IRTreeAndType name(Arena *arena, E_Expr *expr, E_Expr *tag)
#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;
};
////////////////////////////////
//~ rjf: Used Tag Map Data Structure
typedef struct E_UsedTagNode E_UsedTagNode;
struct E_UsedTagNode
{
E_UsedTagNode *next;
E_UsedTagNode *prev;
E_Expr *tag;
};
typedef struct E_UsedTagSlot E_UsedTagSlot;
struct E_UsedTagSlot
{
E_UsedTagNode *first;
E_UsedTagNode *last;
};
typedef struct E_UsedTagMap E_UsedTagMap;
struct E_UsedTagMap
{
U64 slots_count;
E_UsedTagSlot *slots;
};
////////////////////////////////
//~ rjf: Parse Context
@@ -151,6 +213,8 @@ struct E_IRCtx
{
E_String2ExprMap *macro_map;
E_LookupRuleMap *lookup_rule_map;
E_IRGenRuleMap *irgen_rule_map;
E_UsedTagMap *used_tag_map;
};
////////////////////////////////
@@ -165,6 +229,11 @@ local_persist read_only E_LookupRule e_lookup_rule__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),
};
global read_only E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
thread_static E_IRCtx *e_ir_ctx = 0;
@@ -189,6 +258,15 @@ internal void e_lookup_rule_map_insert(Arena *arena, E_LookupRuleMap *map, E_Loo
internal E_LookupRule *e_lookup_rule_from_string(String8 string);
////////////////////////////////
//~ rjf: IR Gen Rules
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);
////////////////////////////////
//~ rjf: IR-ization Functions
@@ -221,11 +299,10 @@ internal E_IRNode *e_irtree_convert_hi(Arena *arena, E_IRNode *c, E_TypeKey out,
internal E_IRNode *e_irtree_resolve_to_value(Arena *arena, E_Mode from_mode, E_IRNode *tree, E_TypeKey type_key);
//- rjf: top-level irtree/type extraction
internal E_IRTreeAndType e_irtree_and_type_from_expr__space(Arena *arena, E_Space *current_space, E_Expr *expr);
internal E_IRTreeAndType e_irtree_and_type_from_expr(Arena *arena, E_Expr *expr);
//- rjf: irtree -> linear ops/bytecode
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_OpList *out);
internal void e_append_oplist_from_irtree(Arena *arena, E_IRNode *root, E_Space *current_space, E_OpList *out);
internal E_OpList e_oplist_from_irtree(Arena *arena, E_IRNode *root);
internal String8 e_bytecode_from_oplist(Arena *arena, E_OpList *oplist);
+158 -1
View File
@@ -15,6 +15,7 @@ global read_only String8 e_multichar_symbol_strings[] =
str8_lit_comp("!="),
str8_lit_comp("&&"),
str8_lit_comp("||"),
str8_lit_comp("=>"),
};
global read_only S64 e_max_precedence = 15;
@@ -649,7 +650,7 @@ internal E_Expr *
e_push_expr(Arena *arena, E_ExprKind kind, void *location)
{
E_Expr *e = push_array(arena, E_Expr, 1);
e->first = e->last = e->next = e->ref = &e_expr_nil;
e->first = e->last = e->next = e->ref = e->first_tag = e->last_tag = &e_expr_nil;
e->location = location;
e->kind = kind;
return e;
@@ -673,6 +674,12 @@ e_expr_remove_child(E_Expr *parent, E_Expr *child)
DLLRemove_NPZ(&e_expr_nil, parent->first, parent->last, child, next, prev);
}
internal void
e_expr_push_tag(E_Expr *parent, E_Expr *child)
{
DLLPushBack_NPZ(&e_expr_nil, parent->first_tag, parent->last_tag, child, next, prev);
}
internal E_Expr *
e_expr_ref(Arena *arena, E_Expr *ref)
{
@@ -744,6 +751,78 @@ e_expr_ref_bswap(Arena *arena, E_Expr *rhs)
return root;
}
internal E_Expr *
e_expr_copy(Arena *arena, E_Expr *src)
{
E_Expr *result = &e_expr_nil;
Temp scratch = scratch_begin(&arena, 1);
{
typedef struct Task Task;
struct Task
{
Task *next;
E_Expr *dst_parent;
E_Expr *src;
B32 is_ref;
B32 is_tag;
};
Task start_task = {0, &e_expr_nil, src};
Task *first_task = &start_task;
Task *last_task = first_task;
for(Task *t = first_task; t != 0; t = t->next)
{
E_Expr *dst = e_push_expr(arena, t->src->kind, t->src->location);
dst->mode = t->src->mode;
dst->space = t->src->space;
dst->type_key = t->src->type_key;
dst->value = t->src->value;
dst->string = push_str8_copy(arena, t->src->string);
dst->bytecode = push_str8_copy(arena, t->src->bytecode);
if(t->dst_parent == &e_expr_nil)
{
result = dst;
}
else if(t->is_ref)
{
t->dst_parent->ref = dst;
}
else if(t->is_tag)
{
e_expr_push_tag(t->dst_parent, dst);
}
else
{
e_expr_push_child(t->dst_parent, dst);
}
if(t->src->ref != &e_expr_nil)
{
Task *task = push_array(scratch.arena, Task, 1);
task->dst_parent = dst;
task->src = t->src->ref;
task->is_ref = 1;
SLLQueuePush(first_task, last_task, task);
}
for(E_Expr *src_child = t->src->first; src_child != &e_expr_nil; src_child = src_child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
task->dst_parent = dst;
task->src = src_child;
SLLQueuePush(first_task, last_task, task);
}
for(E_Expr *src_child = t->src->first_tag; src_child != &e_expr_nil; src_child = src_child->next)
{
Task *task = push_array(scratch.arena, Task, 1);
task->dst_parent = dst;
task->src = src_child;
task->is_tag = 1;
SLLQueuePush(first_task, last_task, task);
}
}
}
scratch_end(scratch);
return result;
}
////////////////////////////////
//~ rjf: Expression Tree -> String Conversions
@@ -1943,6 +2022,44 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to
}
}
// rjf: calls
if(token.kind == E_TokenKind_Symbol &&
str8_match(token_string, str8_lit("("), 0))
{
it += 1;
E_Expr *callee_expr = atom;
E_Expr *call_expr = e_push_expr(arena, E_ExprKind_Call, token_string.str);
e_expr_push_child(call_expr, callee_expr);
for(B32 done = 0; !done && it < it_opl;)
{
E_Token token = e_token_at_it(it, tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit(")"), 0))
{
done = 1;
it += 1;
}
else
{
E_TokenArray idx_expr_parse_tokens = e_token_array_make_first_opl(it, it_opl);
E_Parse arg_parse = e_parse_expr_from_text_tokens__prec(arena, text, tokens, e_max_precedence);
e_msg_list_concat_in_place(&result.msgs, &arg_parse.msgs);
if(arg_parse.expr != &e_expr_nil)
{
e_expr_push_child(call_expr, arg_parse.expr);
}
it = arg_parse.last_token;
E_Token maybe_comma = e_token_at_it(it, tokens);
String8 maybe_comma_string = str8_substr(text, token.range);
if(maybe_comma.kind == E_TokenKind_Symbol && str8_match(maybe_comma_string, str8_lit(","), 0))
{
it += 1;
}
}
}
atom = call_expr;
}
// rjf: quit if this doesn't look like any patterns of postfix unary we know
if(!is_postfix_unary)
{
@@ -2100,6 +2217,46 @@ e_parse_expr_from_text_tokens__prec(Arena *arena, String8 text, E_TokenArray *to
}
}
//- rjf: parse tags
{
if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("=>"), 0))
{
for(B32 done = 0; !done && it < it_opl;)
{
E_Token maybe_identifier = e_token_at_it(it, tokens);
E_Token maybe_open_paren = e_token_at_it(it+1, tokens);
String8 maybe_open_paren_string = str8_substr(text, maybe_open_paren.range);
if(maybe_identifier.kind == E_TokenKind_Identifier &&
maybe_open_paren.kind == E_TokenKind_Symbol &&
str8_match(maybe_open_paren_string, str8_lit("("), 0))
{
E_TokenArray tag_tokens = e_token_array_make_first_opl(it, it_opl);
E_Parse tag_parse = e_parse_expr_from_text_tokens(arena, text, &tag_tokens);
e_msg_list_concat_in_place(&result.msgs, &tag_parse.msgs);
it = tag_parse.last_token;
if(tag_parse.expr != &e_expr_nil)
{
e_expr_push_tag(atom, tag_parse.expr);
}
else
{
done = 1;
}
E_Token maybe_comma = e_token_at_it(it, tokens);
String8 maybe_comma_string = str8_substr(text, token.range);
if(maybe_comma.kind == E_TokenKind_Symbol && str8_match(maybe_comma_string, str8_lit(","), 0))
{
it += 1;
}
}
else
{
done = 1;
}
}
}
}
// rjf: if we parsed nothing successfully, we're done
if(it == start_it)
{
+4
View File
@@ -52,6 +52,8 @@ struct E_Expr
{
E_Expr *first;
E_Expr *last;
E_Expr *first_tag;
E_Expr *last_tag;
E_Expr *next;
E_Expr *prev;
E_Expr *ref;
@@ -218,6 +220,7 @@ internal E_Expr *e_push_expr(Arena *arena, E_ExprKind kind, void *location);
internal void e_expr_insert_child(E_Expr *parent, E_Expr *prev, E_Expr *child);
internal void e_expr_push_child(E_Expr *parent, E_Expr *child);
internal void e_expr_remove_child(E_Expr *parent, E_Expr *child);
internal void e_expr_push_tag(E_Expr *parent, E_Expr *child);
internal E_Expr *e_expr_ref(Arena *arena, E_Expr *ref);
internal E_Expr *e_expr_ref_addr(Arena *arena, E_Expr *rhs);
internal E_Expr *e_expr_ref_member_access(Arena *arena, E_Expr *lhs, String8 member_name);
@@ -225,6 +228,7 @@ internal E_Expr *e_expr_ref_array_index(Arena *arena, E_Expr *lhs, U64 index);
internal E_Expr *e_expr_ref_deref(Arena *arena, E_Expr *rhs);
internal E_Expr *e_expr_ref_cast(Arena *arena, E_TypeKey type_key, E_Expr *rhs);
internal E_Expr *e_expr_ref_bswap(Arena *arena, E_Expr *rhs);
internal E_Expr *e_expr_copy(Arena *arena, E_Expr *src);
////////////////////////////////
//~ rjf: Expression Tree -> String Conversions
+6 -2
View File
@@ -14,7 +14,7 @@ str8_lit_comp("CharLiteral"),
str8_lit_comp("Symbol"),
};
String8 e_expr_kind_strings[49] =
String8 e_expr_kind_strings[51] =
{
str8_lit_comp("Nil"),
str8_lit_comp("Ref"),
@@ -49,6 +49,7 @@ str8_lit_comp("BitOr"),
str8_lit_comp("LogAnd"),
str8_lit_comp("LogOr"),
str8_lit_comp("Ternary"),
str8_lit_comp("Call"),
str8_lit_comp("LeafBytecode"),
str8_lit_comp("LeafMember"),
str8_lit_comp("LeafStringLiteral"),
@@ -65,6 +66,7 @@ str8_lit_comp("Array"),
str8_lit_comp("Func"),
str8_lit_comp("Line"),
str8_lit_comp("Define"),
str8_lit_comp("Tag"),
};
String8 e_interpretation_code_display_strings[11] =
@@ -82,7 +84,7 @@ str8_lit_comp("Insufficient evaluation machine stack space."),
str8_lit_comp("Malformed bytecode."),
};
E_OpInfo e_expr_kind_op_info_table[49] =
E_OpInfo e_expr_kind_op_info_table[51] =
{
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
@@ -117,6 +119,7 @@ E_OpInfo e_expr_kind_op_info_table[49] =
{ E_OpKind_Binary, 11, str8_lit_comp(""), str8_lit_comp("&&"), str8_lit_comp("") },
{ E_OpKind_Binary, 12, str8_lit_comp(""), str8_lit_comp("||"), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp("?"), str8_lit_comp(":") },
{ E_OpKind_Null, 0, str8_lit_comp("("), str8_lit_comp(","), str8_lit_comp(")") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
@@ -133,6 +136,7 @@ E_OpInfo e_expr_kind_op_info_table[49] =
{ E_OpKind_Null, 0, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("") },
{ E_OpKind_Binary, 1, str8_lit_comp(""), str8_lit_comp(":"), str8_lit_comp("") },
{ E_OpKind_Binary, 13, str8_lit_comp(""), str8_lit_comp("="), str8_lit_comp("") },
{ E_OpKind_Null, 0, str8_lit_comp("=>"), str8_lit_comp(","), str8_lit_comp("") },
};
U8 e_kind_basic_byte_size_table[57] =
+4 -2
View File
@@ -125,6 +125,7 @@ E_ExprKind_BitOr,
E_ExprKind_LogAnd,
E_ExprKind_LogOr,
E_ExprKind_Ternary,
E_ExprKind_Call,
E_ExprKind_LeafBytecode,
E_ExprKind_LeafMember,
E_ExprKind_LeafStringLiteral,
@@ -141,6 +142,7 @@ E_ExprKind_Array,
E_ExprKind_Func,
E_ExprKind_Line,
E_ExprKind_Define,
E_ExprKind_Tag,
E_ExprKind_COUNT,
} E_ExprKindEnum;
@@ -162,9 +164,9 @@ E_InterpretationCode_COUNT,
C_LINKAGE_BEGIN
extern String8 e_token_kind_strings[6];
extern String8 e_expr_kind_strings[49];
extern String8 e_expr_kind_strings[51];
extern String8 e_interpretation_code_display_strings[11];
extern E_OpInfo e_expr_kind_op_info_table[49];
extern E_OpInfo e_expr_kind_op_info_table[51];
extern U8 e_kind_basic_byte_size_table[57];
extern String8 e_kind_basic_string_table[57];