eval2 checkpoint: type operations, constructed types, checkpoint before splitting back to frontend / compiler split - we need to do things with the parse tree that we can't with an ir tree

This commit is contained in:
Ryan Fleury
2026-06-25 13:50:16 -07:00
parent c1b3461709
commit 6b52d68c62
7 changed files with 745 additions and 22 deletions
+32 -6
View File
@@ -9,6 +9,13 @@ target:
debug_subprocesses: 0
}
target:
{
executable: "build/raddbg.exe"
working_directory: "../raddebugger"
arguments: "--user:test123"
debug_subprocesses: 0
}
target:
{
executable: "build/mule_main.exe"
working_directory: build
@@ -18,6 +25,7 @@ target:
{
executable: "build/torture.exe"
working_directory: build
arguments: "raddbg/*"
}
target:
{
@@ -31,14 +39,32 @@ target:
arguments: "--rdi raddbg"
}
target:
{
executable: "build/release_version/raddbg.exe"
working_directory: "build/release_version"
}
target:
{
executable: "build/radbin.exe"
working_directory: build
arguments: "--rdi fat.so --capture"
}
target:
{
executable: "build/radbin.exe"
working_directory: build
arguments: "--rdi fat.debug --capture"
}
target:
{
executable: "build/radbin.exe"
working_directory: build
arguments: "--rdi raddbg"
}
watch_pin: expression: tag_hash_slots
target:
{
executable: "build/ryan_scratch.exe"
working_directory: build
enabled: 1
}
target:
{
executable: "build/raddbg.exe"
working_directory: build
arguments: "--bin --dump test123.rdi"
}
+607 -8
View File
@@ -163,6 +163,153 @@ e2_dbgi_from_num(U32 num)
return result;
}
////////////////////////////////
//~ rjf: Constructed Types
internal E2_ConsTypeMap *
e2_cons_type_map_alloc(void)
{
Arena *arena = arena_alloc();
E2_ConsTypeMap *map = push_array(arena, E2_ConsTypeMap, 1);
map->arena = arena;
map->table_start_arena_pos = arena_pos(arena);
return map;
}
internal void
e2_select_cons_type_map(E2_ConsTypeMap *map)
{
arena_pop_to(map->arena, map->table_start_arena_pos);
map->slots_count = 256;
map->content_slots = push_array(map->arena, E2_ConsTypeSlot, map->slots_count);
map->id_slots = push_array(map->arena, E2_ConsTypeSlot, map->slots_count);
e2_cons_type_map = map;
}
internal B32
e2_cons_type_params_match(E2_ConsTypeParams *a, E2_ConsTypeParams *b)
{
B32 result = (a->arch == b->arch &&
a->kind == b->kind &&
str8_match(a->name, b->name, 0) &&
e2_type_key_match(a->direct, b->direct) &&
a->count == b->count &&
a->depth == b->depth &&
a->args == 0 && b->args == 0);
return result;
}
internal E2_ConsTypeNode *
e2_cons_type_node_from_params(E2_ConsTypeParams *params)
{
E2_ConsTypeMap *map = e2_cons_type_map;
// rjf: params -> hash
U64 hash = 0;
{
hash = u64_hash_from_seed_str8(hash, str8_struct(&params->arch));
hash = u64_hash_from_seed_str8(hash, str8_struct(&params->kind));
hash = u64_hash_from_seed_str8(hash, str8_struct(&params->name));
hash = u64_hash_from_seed_str8(hash, str8_struct(&params->direct));
hash = u64_hash_from_seed_str8(hash, str8_struct(&params->count));
hash = u64_hash_from_seed_str8(hash, str8_struct(&params->depth));
}
// rjf: hash -> content slot
U64 content_slot_idx = hash%map->slots_count;
E2_ConsTypeSlot *content_slot = &map->content_slots[content_slot_idx];
// rjf: parameters -> existing node
E2_ConsTypeNode *node = 0;
for(E2_ConsTypeNode *n = content_slot->first; n != 0; n = n->content_next)
{
if(e2_cons_type_params_match(&n->params, params))
{
node = n;
break;
}
}
// rjf: if node wasn't found -> push into the map
if(node == 0)
{
// rjf: form node ID
map->id_gen += 1;
U64 id = map->id_gen;
// rjf: build the node
node = push_array(map->arena, E2_ConsTypeNode, 1);
SLLQueuePush_N(content_slot->first, content_slot->last, node, content_next);
node->id = id;
MemoryCopyStruct(&node->params, params);
node->params.name = str8_copy(map->arena, node->params.name);
// TODO(rjf): double check once we're doing type expression
// arguments that we don't need a deep copy of the args here.
switch(node->params.kind)
{
default:
{
node->byte_size = e2_byte_size_from_type_key(node->params.direct);
}break;
case E2_TypeKind_Ptr:
case E2_TypeKind_Function:
case E2_TypeKind_Method:
case E2_TypeKind_MemberPtr:
case E2_TypeKind_RRef:
case E2_TypeKind_LRef:
{
node->byte_size = byte_size_from_arch(node->params.arch);
}break;
case E2_TypeKind_Array:
{
node->byte_size = node->params.count * e2_byte_size_from_type_key(node->params.direct);
}break;
}
// rjf: insert node into the ID slots
{
U64 id_hash = u64_hash_from_str8(str8_struct(&id));
U64 id_slot_idx = id_hash%map->slots_count;
E2_ConsTypeSlot *id_slot = &map->id_slots[id_slot_idx];
SLLQueuePush_N(id_slot->first, id_slot->last, node, id_next);
}
}
return node;
}
internal E2_ConsTypeNode *
e2_cons_type_node_from_id(U64 id)
{
E2_ConsTypeMap *map = e2_cons_type_map;
U64 id_hash = u64_hash_from_str8(str8_struct(&id));
U64 id_slot_idx = id_hash%map->slots_count;
E2_ConsTypeSlot *id_slot = &map->id_slots[id_slot_idx];
E2_ConsTypeNode *node = &e2_cons_type_node_nil;
for(E2_ConsTypeNode *n = id_slot->first; n != 0; n = n->id_next)
{
if(n->id == id)
{
node = n;
break;
}
}
return node;
}
internal E2_TypeKey
e2_type_key_from_cons_type_node(E2_ConsTypeNode *node)
{
E2_TypeKey key =
{
.kind = E2_TypeKeyKind_Cons,
.u32[0] = node->params.kind,
.u32[1] = (U32)((node->id&0xffffffff00000000ull) >> 32),
.u32[2] = node->id&0xffffffffull,
};
return key;
}
////////////////////////////////
//~ rjf: Type Keys
@@ -371,8 +518,8 @@ e2_type_key_reg(Arch arch, ARCH_RegCode reg_code)
internal E2_TypeKey
e2_type_key_cons_(E2_ConsTypeParams *params)
{
E2_TypeKey result = {E2_TypeKeyKind_Null};
// TODO(rjf)
E2_ConsTypeNode *node = e2_cons_type_node_from_params(params);
E2_TypeKey result = e2_type_key_from_cons_type_node(node);
return result;
}
@@ -428,7 +575,9 @@ e2_byte_size_from_type_key(E2_TypeKey k)
}break;
case E2_TypeKeyKind_Cons:
{
// TODO(rjf)
U64 id = e2_cons_type_id_from_key(k);
E2_ConsTypeNode *node = e2_cons_type_node_from_id(id);
result = node->byte_size;
}break;
case E2_TypeKeyKind_Reg:
{
@@ -475,6 +624,17 @@ e2_dbgi_type_idx_from_key(E2_TypeKey k)
return result;
}
internal U64
e2_cons_type_id_from_key(E2_TypeKey k)
{
U64 result = 0;
if(k.kind == E2_TypeKeyKind_Cons)
{
result = ((U64)k.u32[1] << 32) | k.u32[2];
}
return result;
}
internal U64
e2_shift_from_type_key(E2_TypeKey k)
{
@@ -540,7 +700,9 @@ e2_arch_from_type_key(E2_TypeKey k)
}break;
case E2_TypeKeyKind_Cons:
{
// TODO(rjf)
U64 id = e2_cons_type_id_from_key(k);
E2_ConsTypeNode *node = e2_cons_type_node_from_id(id);
arch = node->params.arch;
}break;
case E2_TypeKeyKind_Reg:
{
@@ -558,7 +720,104 @@ e2_type_deep_match(E2_TypeKey l, E2_TypeKey r)
B32 result = e2_type_key_match(l, r);
if(!result)
{
// TODO(rjf)
Temp scratch = scratch_begin(0, 0);
typedef struct Task Task;
struct Task
{
Task *next;
E2_TypeKey k;
U64 member_num;
};
Task *free_task = 0;
Task l_start_task = {0, l};
Task r_start_task = {0, r};
Task *l_top = &l_start_task;
Task *r_top = &r_start_task;
U64 l_hash = 0;
U64 r_hash = 0;
result = 1;
for(;l_top != 0 || r_top != 0;)
{
// rjf: mismatched task structures -> immediately mark as a non-match & break
if((l_top && !r_top) || (!l_top && r_top))
{
result = 0;
break;
}
// rjf: mismatched hashes -> immediately mark as a non-match & break
if(l_hash != r_hash)
{
result = 0;
break;
}
// rjf: do next step of hash
Task **task_tops[] = {&l_top, &r_top};
E2_TypeKey keys[] = {l_top->k, r_top->k};
U64 *hash_ptrs[] = {&l_hash, &r_hash};
for EachElement(key_idx, keys)
{
Task *top = task_tops[key_idx][0];
E2_TypeKey key = keys[key_idx];
E2_TypeKind kind = e2_type_kind_from_key(key);
// rjf: have not advanced to members -> mix in kind / byte size
if(top->member_num == 0)
{
U64 byte_size = e2_byte_size_from_type_key(key);
hash_ptrs[key_idx][0] = u64_hash_from_seed_str8(hash_ptrs[key_idx][0], str8_struct(&kind));
hash_ptrs[key_idx][0] = u64_hash_from_seed_str8(hash_ptrs[key_idx][0], str8_struct(&byte_size));
}
// rjf: advance to next member
B32 has_next_member = 0;
if(kind == E2_TypeKind_Struct ||
kind == E2_TypeKind_Union ||
kind == E2_TypeKind_Class ||
kind == E2_TypeKind_Enum)
{
U32 dbgi_num = e2_dbgi_num_from_type_key(key);
U32 type_idx = e2_dbgi_type_idx_from_key(key);
E2_DbgInfo *dbgi = e2_dbgi_from_num(dbgi_num);
RDI_TypeNode *type_node = rdi_element_from_name_idx(dbgi->rdi, TypeNodes, type_idx);
String8 name = str8_from_rdi_string_idx(dbgi->rdi, type_node->user_defined.name_string_idx);
hash_ptrs[key_idx][0] = u64_hash_from_seed_str8(hash_ptrs[key_idx][0], name);
RDI_UDT *udt = rdi_element_from_name_idx(dbgi->rdi, UDTs, type_node->user_defined.udt_idx);
U64 next_member_num = top->member_num + 1;
if(next_member_num <= udt->member_count)
{
has_next_member = 1;
RDI_Member *member = rdi_element_from_name_idx(dbgi->rdi, Members, next_member_num-1);
RDI_TypeNode *member_type_node = rdi_element_from_name_idx(dbgi->rdi, TypeNodes, member->type_idx);
String8 member_name = str8_from_rdi_string_idx(dbgi->rdi, member->name_string_idx);
hash_ptrs[key_idx][0] = u64_hash_from_seed_str8(hash_ptrs[key_idx][0], str8_struct(&member->off));
hash_ptrs[key_idx][0] = u64_hash_from_seed_str8(hash_ptrs[key_idx][0], member_name);
Task *member_task = free_task;
if(member_task != 0)
{
SLLStackPop(free_task);
}
else
{
member_task = push_array_no_zero(scratch.arena, Task, 1);
}
MemoryZeroStruct(&member_task);
member_task->k = e2_type_key_dbgi(e2_type_kind_from_rdi(member_type_node->kind), dbgi_num, member->type_idx);
SLLStackPush(task_tops[key_idx][0], member_task);
}
}
// rjf: if we don't have a subsequent member, pop this task
if(!has_next_member)
{
Task *popped = task_tops[key_idx][0];
SLLStackPop(task_tops[key_idx][0]);
SLLStackPush(free_task, popped);
}
}
}
scratch_end(scratch);
}
return result;
}
@@ -596,7 +855,9 @@ e2_type_key_direct(E2_TypeKey k)
}break;
case E2_TypeKeyKind_Cons:
{
// TODO(rjf)
U64 id = e2_cons_type_id_from_key(k);
E2_ConsTypeNode *node = e2_cons_type_node_from_id(id);
result = node->params.direct;
}break;
case E2_TypeKeyKind_Reg:{}break;
}
@@ -955,6 +1216,235 @@ e2_expr_push_child(Arena *arena, E2_Expr *parent, E2_Expr *expr)
e2_expr_push_child_node(parent, n);
}
////////////////////////////////
//~ rjf: Expression Constructors
internal E2_IRNode *
e2_irnode(Arena *arena)
{
E2_IRNode *expr = push_array(arena, E2_IRNode, 1);
MemoryCopyStruct(expr, &e2_irnode_nil);
return expr;
}
internal E2_IRNode *
e2_irnode_const_u64_or_smaller(Arena *arena, U64 u)
{
E2_IRNode *e = e2_irnode(arena);
{
e->mode = E2_Mode_Value;
e->val.u64 = u;
if(u <= 0x7fffffff)
{
e->op = RDI_EvalOp_ConstU32;
e->type_key = e2_type_key_basic(E2_TypeKind_S32);
}
else if(u <= 0xffffffff)
{
e->op = RDI_EvalOp_ConstU32;
e->type_key = e2_type_key_basic(E2_TypeKind_U32);
}
else if(u <= 0x7fffffffffffffffull)
{
e->op = RDI_EvalOp_ConstU64;
e->type_key = e2_type_key_basic(E2_TypeKind_S64);
}
else if(u <= 0xffffffffffffffffull)
{
e->op = RDI_EvalOp_ConstU64;
e->type_key = e2_type_key_basic(E2_TypeKind_U64);
}
}
return e;
}
internal E2_IRNode *
e2_irnode_const_f32(Arena *arena, F32 f32)
{
E2_IRNode *e = e2_irnode(arena);
e->mode = E2_Mode_Value;
e->val.f32 = f32;
e->op = RDI_EvalOp_ConstU32;
e->type_key = e2_type_key_basic(E2_TypeKind_F32);
return e;
}
internal E2_IRNode *
e2_irnode_const_f64(Arena *arena, F64 f64)
{
E2_IRNode *e = e2_irnode(arena);
e->mode = E2_Mode_Value;
e->val.f64 = f64;
e->op = RDI_EvalOp_ConstU64;
e->type_key = e2_type_key_basic(E2_TypeKind_F64);
return e;
}
internal E2_IRNode *
e2_irnode_unary_op(Arena *arena, E2_TypeKey type_key, RDI_EvalOp op, E2_IRNode *operand)
{
E2_IRNode *e = e2_irnode(arena);
e->type_key = type_key;
e->op = op;
e->mode = E2_Mode_Value;
e->val.u512.u8[0] = e2_type_group_from_kind(e2_type_kind_from_key(type_key));
e->val.u512.u8[1] = 8*e2_byte_size_from_type_key(type_key);
e2_irnode_push_child(arena, e, operand);
return e;
}
internal E2_IRNode *
e2_irnode_binary_op(Arena *arena, E2_TypeKey type_key, RDI_EvalOp op, E2_IRNode *lhs, E2_IRNode *rhs)
{
E2_IRNode *e = e2_irnode(arena);
E2_TypeKey arith_type_key = type_key;
if(RDI_EvalOp_FirstLogical <= op && op <= RDI_EvalOp_LastLogical)
{
arith_type_key = lhs->type_key;
}
e->type_key = type_key;
e->op = op;
e->mode = E2_Mode_Value;
e->val.u512.u8[0] = e2_type_group_from_kind(e2_type_kind_from_key(arith_type_key));
e->val.u512.u8[1] = 8*e2_byte_size_from_type_key(arith_type_key);
e2_irnode_push_child(arena, e, lhs);
e2_irnode_push_child(arena, e, rhs);
return e;
}
internal E2_IRNode *
e2_irnode_resolve_to_value(Arena *arena, E2_IRNode *expr)
{
E2_IRNode *result = expr;
// rjf: address evaluations of arrays -> create value of pointer to first element
if(expr->mode == E2_Mode_Address && e2_type_kind_from_key(e2_type_key_undecorate(expr->type_key)) == E2_TypeKind_Array)
{
result = e2_irnode(arena);
result->type_key = e2_type_key_direct(e2_type_key_undecorate(expr->type_key));
result->mode = E2_Mode_Value;
e2_irnode_push_child(arena, result, expr);
}
// rjf: address evaluations -> read value from space
else if(expr->mode == E2_Mode_Address)
{
U64 memread_byte_size = e2_byte_size_from_type_key(expr->type_key);
memread_byte_size = Min(64, memread_byte_size);
E2_IRNode *memread_expr = e2_irnode(arena);
memread_expr->op = RDI_EvalOp_MemRead;
memread_expr->mode = E2_Mode_Value;
memread_expr->type_key = expr->type_key;
memread_expr->val.u64 = memread_byte_size;
e2_irnode_push_child(arena, memread_expr, expr);
result = memread_expr;
}
// rjf: bitfields -> shift & mask
E2_TypeKey core_type_key = e2_type_key_undecorate(expr->type_key);
if(e2_type_kind_from_key(core_type_key) == E2_TypeKind_Bitfield)
{
// rjf: unpack bitfield params
U64 shift = e2_shift_from_type_key(result->type_key);
U64 mask_count = e2_mask_count_from_type_key(result->type_key);
U64 valid_bits_mask = 0;
for EachIndex(idx, mask_count)
{
valid_bits_mask |= (1ull<<idx);
}
// rjf: mask(shift(expr, count), bitmask)
E2_IRNode *shift_expr = e2_irnode_binary_op(arena, e2_type_key_basic(E2_TypeKind_U64), RDI_EvalOp_RShift, result, e2_irnode_const_u64_or_smaller(arena, shift));
E2_IRNode *mask_expr = e2_irnode_binary_op(arena, e2_type_key_direct(core_type_key), RDI_EvalOp_BitAnd, shift_expr, e2_irnode_const_u64_or_smaller(arena, valid_bits_mask));
result = mask_expr;
}
return result;
}
internal E2_IRNode *
e2_irnode_truncate(Arena *arena, E2_IRNode *expr, E2_TypeKey dst_type_key)
{
E2_IRNode *result = expr;
E2_TypeKind dst_type_kind = e2_type_kind_from_key(dst_type_key);
U64 dst_type_byte_size = e2_byte_size_from_type_key(dst_type_key);
B32 dst_type_is_signed = e2_type_kind_is_signed(dst_type_kind);
if(dst_type_byte_size < 64)
{
result = e2_irnode(arena);
result->type_key = dst_type_key;
result->op = dst_type_is_signed ? RDI_EvalOp_TruncSigned : RDI_EvalOp_Trunc;
result->val.u64 = dst_type_byte_size*8;
e2_irnode_push_child(arena, result, expr);
}
return result;
}
internal E2_IRNode *
e2_irnode_convert_if_possible(Arena *arena, E2_IRNode *expr, E2_TypeKey dst_type_key)
{
E2_IRNode *result = expr;
{
// rjf: unpack src / dst types
E2_TypeKey src_type_key = expr->type_key;
E2_TypeKind src_type_kind = e2_type_kind_from_key(src_type_key);
E2_TypeKind dst_type_kind = e2_type_kind_from_key(dst_type_key);
RDI_EvalTypeGroup src_type_group = e2_type_group_from_kind(src_type_kind);
RDI_EvalTypeGroup dst_type_group = e2_type_group_from_kind(dst_type_kind);
U64 src_byte_size = e2_byte_size_from_type_key(src_type_key);
U64 dst_byte_size = e2_byte_size_from_type_key(dst_type_key);
// rjf: convert from src -> dst
RDI_EvalConversionKind conversion_kind = rdi_eval_conversion_kind_from_typegroups(src_type_group, dst_type_group);
if(conversion_kind == RDI_EvalConversionKind_Legal)
{
result = e2_irnode(arena);
result->mode = E2_Mode_Value;
result->type_key = dst_type_key;
result->op = RDI_EvalOp_Convert;
result->val.u64 = src_type_group | (dst_type_group << 8);
e2_irnode_push_child(arena, result, expr);
}
// rjf: no-op from src -> dst
if(conversion_kind == RDI_EvalConversionKind_Noop)
{
result->type_key = dst_type_key;
}
// rjf: if shrinking integer sizes, truncate
if(dst_byte_size < src_byte_size && e2_type_kind_is_integer(dst_type_kind))
{
result = e2_irnode_truncate(arena, expr, dst_type_key);
}
}
return result;
}
internal E2_IRNode *
e2_irnode_type(Arena *arena, E2_TypeKey type_key)
{
E2_IRNode *expr = e2_irnode(arena);
expr->type_key = type_key;
expr->mode = E2_Mode_Type;
return expr;
}
internal void
e2_irnode_push_child_node(E2_IRNode *parent, E2_IRNodePtrNode *node)
{
SLLQueuePush(parent->first_child, parent->last_child, node);
parent->child_count += 1;
}
internal void
e2_irnode_push_child(Arena *arena, E2_IRNode *parent, E2_IRNode *expr)
{
E2_IRNodePtrNode *n = push_array(arena, E2_IRNodePtrNode, 1);
n->v = expr;
e2_irnode_push_child_node(parent, n);
}
////////////////////////////////
//~ rjf: String -> Expression
@@ -1319,9 +1809,29 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, E
{
String8 identifier = str8_substr(string, token.range);
B32 identifier_mapped = 0;
B32 definitions_are_allowed = (state->top_task == 0 || state->top_task->op_kind != E2_OpKind_Macro);
// rjf: if we're currently parsing a macro definition, then we first want to try
// resolving identifiers as macro arguments
if(!identifier_mapped && state->top_task != 0 && state->top_task->op_kind == E2_OpKind_Macro)
{
U64 arg_num = 1;
for(String8Node *n = state->top_task->macro_arg_names.first; n != 0; n = n->next, arg_num += 1)
{
if(str8_match(n->string, identifier, 0))
{
identifier_mapped = 1;
expr = e2_expr(arena);
expr->op = E2_EvalOp_LeafMacroArgument;
expr->val.u64 = arg_num;
expr->mode = E2_Mode_Value;
break;
}
}
}
// rjf: first try to resolve as a definition
if(!identifier_mapped && e2_try_token(string, E2_TokenKind_Symbol, s("="), &off, 0))
if(definitions_are_allowed && !identifier_mapped && e2_try_token(string, E2_TokenKind_Symbol, s("="), &off, 0))
{
identifier_mapped = 1;
E2_ParseTask *task = state->free_task;
@@ -1342,6 +1852,74 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, E
SLLStackPush(state->top_task, task);
}
// rjf: try to resolve it as a macro definition
if(definitions_are_allowed && !identifier_mapped)
{
U64 macro_off = off;
if(e2_try_token(string, E2_TokenKind_Symbol, s("("), &macro_off, 0))
{
U64 post_macro_paren_off = macro_off;
B32 looks_like_macro_def = 1;
U64 macro_arg_count = 0;
for(;macro_off < string.size;)
{
if(!e2_try_token(string, E2_TokenKind_Identifier, s(""), &macro_off, 0))
{
looks_like_macro_def = 0;
break;
}
macro_arg_count += 1;
e2_try_token(string, E2_TokenKind_Symbol, s(","), &macro_off, 0);
if(e2_try_token(string, E2_TokenKind_Symbol, s(")"), &macro_off, 0))
{
break;
}
}
if(looks_like_macro_def && e2_try_token(string, E2_TokenKind_Symbol, s("="), &macro_off, 0))
{
// rjf: push task to fill macro definition
identifier_mapped = 1;
E2_ParseTask *task = state->free_task;
if(task != 0)
{
SLLStackPop(state->free_task);
}
else
{
task = push_array_no_zero(arena, E2_ParseTask, 1);
}
MemoryZeroStruct(task);
task->src_range = token.range;
task->child_count_target = 1;
task->op_kind = E2_OpKind_Macro;
task->max_precedence = max_S64;
task->identifier = identifier;
SLLStackPush(state->top_task, task);
// rjf: gather argument names
macro_off = post_macro_paren_off;
for(;macro_off < string.size;)
{
E2_Token next_token = {0};
if(!e2_try_token(string, E2_TokenKind_Identifier, s(""), &macro_off, &next_token))
{
break;
}
str8_list_push(arena, &task->macro_arg_names, str8_substr(string, next_token.range));
e2_try_token(string, E2_TokenKind_Symbol, s(","), &macro_off, 0);
if(e2_try_token(string, E2_TokenKind_Symbol, s(")"), &macro_off, 0))
{
break;
}
}
e2_try_token(string, E2_TokenKind_Symbol, s("="), &macro_off, 0);
// rjf: advance offset to past '='
off = macro_off;
}
}
}
// rjf: first try to resolve as an operator name
if(!identifier_mapped)
{
@@ -2102,6 +2680,23 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, E2_ExprMap *expr_map, E
}
}break;
//- rjf: macros
case E2_OpKind_Macro:
{
if(completed_with_caller_info)
{
finished_root = &e2_expr_nil;
}
else
{
done = 1;
parse.status = E2_ParseStatus_NewIdentifierDefinition;
parse.expr = lhs;
parse.identifier = completed_task->identifier;
state->caller_info_completes_task = 1;
}
}break;
//- rjf: conditionals
case E2_OpKind_Cond:
{
@@ -2459,7 +3054,11 @@ e2_interp_from_bytecode(Arena *arena, E2_InterpState *state, E2_SpaceMap *space_
U64 ctx_base_addr = 0;
switch(op)
{
default:{}break;
default:
{
good = 0;
interp.status = E2_InterpStatus_UnsupportedOp;
}break;
case E2_EvalOp_SetCtxID:
{
+97 -5
View File
@@ -39,6 +39,7 @@ struct E2_OpInfo
enum
{
E2_EvalOp_SetCtxID = RDI_EvalOp_COUNT,
E2_EvalOp_LeafMacroArgument,
};
////////////////////////////////
@@ -67,6 +68,32 @@ E2_ParseStatus;
#define e2_parse_status_is_terminal(s) (E2_ParseStatus_FirstTerminal <= (s) && (s) <= E2_ParseStatus_LastTerminal)
#define e2_parse_status_is_caller_request(s) (E2_ParseStatus_FirstCallerRequest <= (s) && (s) <= E2_ParseStatus_LastCallerRequest)
////////////////////////////////
//~ rjf: Compiler Statuses
typedef enum E2_CompileStatus
{
//- rjf: terminals
E2_CompileStatus_Good,
E2_CompileStatus_Error,
E2_CompileStatus_FirstTerminal = E2_CompileStatus_Good,
E2_CompileStatus_LastTerminal = E2_CompileStatus_Error,
//- rjf: caller-provided info
E2_CompileStatus_MissedIdentifierResolution,
E2_CompileStatus_NewIdentifierDefinition,
E2_CompileStatus_MemberAccess,
E2_CompileStatus_IndexAccess,
E2_CompileStatus_Call,
E2_CompileStatus_CompileTimeEval,
E2_CompileStatus_FirstCallerRequest = E2_CompileStatus_MissedIdentifierResolution,
E2_CompileStatus_LastCallerRequest = E2_CompileStatus_CompileTimeEval,
}
E2_CompileStatus;
#define e2_compile_status_is_terminal(s) (E2_CompileStatus_FirstTerminal <= (s) && (s) <= E2_CompileStatus_LastTerminal)
#define e2_compile_status_is_caller_request(s) (E2_CompileStatus_FirstCallerRequest <= (s) && (s) <= E2_CompileStatus_LastCallerRequest)
////////////////////////////////
//~ rjf: Interpretation Statuses
@@ -152,9 +179,9 @@ struct E2_ConsTypeParams
typedef struct E2_ConsTypeNode E2_ConsTypeNode;
struct E2_ConsTypeNode
{
E2_ConsTypeNode *key_next;
E2_ConsTypeNode *id_next;
E2_ConsTypeNode *content_next;
E2_TypeKey key;
U64 id;
E2_ConsTypeParams params;
U64 byte_size;
};
@@ -169,11 +196,12 @@ struct E2_ConsTypeSlot
typedef struct E2_ConsTypeMap E2_ConsTypeMap;
struct E2_ConsTypeMap
{
Arena *arena;
U64 id_gen;
U64 content_slots_count;
U64 table_start_arena_pos;
U64 slots_count;
E2_ConsTypeSlot *content_slots;
U64 key_slots_count;
E2_ConsTypeSlot *key_slots;
E2_ConsTypeSlot *id_slots;
};
////////////////////////////////
@@ -340,6 +368,7 @@ struct E2_ParseTask
String8 expected_closer;
String8 expected_splitter;
B32 splitter_is_required;
String8List macro_arg_names;
};
typedef struct E2_ParseState E2_ParseState;
@@ -381,6 +410,40 @@ struct E2_Parse
E2_MsgList msgs;
};
////////////////////////////////
//~ rjf: IR Tree Building
typedef struct E2_IRNodePtrNode E2_IRNodePtrNode;
struct E2_IRNodePtrNode
{
E2_IRNodePtrNode *next;
struct E2_IRNode *v;
};
typedef struct E2_IRNode E2_IRNode;
struct E2_IRNode
{
E2_IRNodePtrNode *first_child;
E2_IRNodePtrNode *last_child;
U64 child_count;
RDI_EvalOp op;
String8 string;
E2_TypeKey type_key;
E2_Mode mode;
E2_Val val;
};
typedef struct E2_Compile E2_Compile;
struct E2_Compile
{
E2_CompileStatus status;
String8 identifier;
E2_Expr *expr;
String8 member_name;
E2_Expr *params_expr;
E2_MsgList msgs;
};
////////////////////////////////
//~ rjf: Interpretation
@@ -433,9 +496,11 @@ struct E2_Interp
//~ rjf: Globals
thread_static E2_Assets *e2_assets = 0;
thread_static E2_ConsTypeMap *e2_cons_type_map = 0;
read_only global E2_ConsTypeNode e2_cons_type_node_nil = {&e2_cons_type_node_nil, &e2_cons_type_node_nil};
read_only global E2_DbgInfo e2_dbg_info_nil = {{0}, &rdi_parsed_nil};
read_only global E2_Expr e2_expr_nil = {0};
read_only global E2_IRNode e2_irnode_nil = {0};
////////////////////////////////
//~ rjf: Space -> Memory Map Helpers
@@ -461,6 +526,16 @@ internal E2_Msg *e2_msgf(Arena *arena, E2_MsgList *msgs, Rng1U64 src_range, char
internal void e2_select_assets(E2_Assets *assets);
internal E2_DbgInfo *e2_dbgi_from_num(U32 num);
////////////////////////////////
//~ rjf: Constructed Types
internal E2_ConsTypeMap *e2_cons_type_map_alloc(void);
internal void e2_select_cons_type_map(E2_ConsTypeMap *map);
internal B32 e2_cons_type_params_match(E2_ConsTypeParams *a, E2_ConsTypeParams *b);
internal E2_ConsTypeNode *e2_cons_type_node_from_params(E2_ConsTypeParams *params);
internal E2_ConsTypeNode *e2_cons_type_node_from_id(U64 id);
internal E2_TypeKey e2_type_key_from_cons_type_node(E2_ConsTypeNode *node);
////////////////////////////////
//~ rjf: Type Keys
@@ -496,6 +571,7 @@ internal U64 e2_byte_size_from_type_key(E2_TypeKey k);
internal U32 e2_dbgi_num_from_type_key(E2_TypeKey k);
internal E2_DbgInfo *e2_dbgi_from_type_key(E2_TypeKey k);
internal U32 e2_dbgi_type_idx_from_key(E2_TypeKey k);
internal U64 e2_cons_type_id_from_key(E2_TypeKey k);
internal U64 e2_shift_from_type_key(E2_TypeKey k);
internal U64 e2_mask_count_from_type_key(E2_TypeKey k);
internal Arch e2_arch_from_type_key(E2_TypeKey k);
@@ -543,6 +619,22 @@ internal E2_Expr *e2_expr_type(Arena *arena, E2_TypeKey type_key);
internal void e2_expr_push_child_node(E2_Expr *parent, E2_ExprNode *node);
internal void e2_expr_push_child(Arena *arena, E2_Expr *parent, E2_Expr *expr);
////////////////////////////////
//~ rjf: IR Tree Constructors
internal E2_IRNode *e2_irnode(Arena *arena);
internal E2_IRNode *e2_irnode_const_u64_or_smaller(Arena *arena, U64 u);
internal E2_IRNode *e2_irnode_const_f32(Arena *arena, F32 f32);
internal E2_IRNode *e2_irnode_const_f64(Arena *arena, F64 f64);
internal E2_IRNode *e2_irnode_unary_op(Arena *arena, E2_TypeKey type_key, RDI_EvalOp op, E2_IRNode *operand);
internal E2_IRNode *e2_irnode_binary_op(Arena *arena, E2_TypeKey type_key, RDI_EvalOp op, E2_IRNode *lhs, E2_IRNode *rhs);
internal E2_IRNode *e2_irnode_resolve_to_value(Arena *arena, E2_IRNode *expr);
internal E2_IRNode *e2_irnode_truncate(Arena *arena, E2_IRNode *expr, E2_TypeKey dst_type_key);
internal E2_IRNode *e2_irnode_convert_if_possible(Arena *arena, E2_IRNode *expr, E2_TypeKey dst_type_key);
internal E2_IRNode *e2_irnode_type(Arena *arena, E2_TypeKey type_key);
internal void e2_irnode_push_child_node(E2_IRNode *parent, E2_IRNodePtrNode *node);
internal void e2_irnode_push_child(Arena *arena, E2_IRNode *parent, E2_IRNode *expr);
////////////////////////////////
//~ rjf: String -> Expression
+1
View File
@@ -36,6 +36,7 @@ E2_OpTable:
{LogAnd Binary 11 "" "&&" "" "" }
{LogOr Binary 12 "" "||" "" "" }
{Define Null 13 "" "=" "" "" }
{Macro Null 14 "" "" "" "" }
{Cond Ternary 14 "" "?" "" ":"}
}
+3 -2
View File
@@ -4,7 +4,7 @@
//- GENERATED CODE
C_LINKAGE_BEGIN
E2_OpInfo e2_op_kind_info_table[34] =
E2_OpInfo e2_op_kind_info_table[35] =
{
{0},
{E2_OpParseKind_Binary, 1, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp(""), str8_lit_comp("")},
@@ -38,7 +38,8 @@ E2_OpInfo e2_op_kind_info_table[34] =
{E2_OpParseKind_Binary, 10, str8_lit_comp(""), str8_lit_comp("|"), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Binary, 11, str8_lit_comp(""), str8_lit_comp("&&"), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Binary, 12, str8_lit_comp(""), str8_lit_comp("||"), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Binary, 13, str8_lit_comp(""), str8_lit_comp("="), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Null, 13, str8_lit_comp(""), str8_lit_comp("="), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Null, 14, str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp("")},
{E2_OpParseKind_Ternary, 14, str8_lit_comp(""), str8_lit_comp("?"), str8_lit_comp(""), str8_lit_comp(":")},
};
+2 -1
View File
@@ -41,6 +41,7 @@ E2_OpKind_BitOr,
E2_OpKind_LogAnd,
E2_OpKind_LogOr,
E2_OpKind_Define,
E2_OpKind_Macro,
E2_OpKind_Cond,
E2_OpKind_COUNT,
} E2_OpKind;
@@ -124,7 +125,7 @@ E2_TypeKind_LastMeta = E2_TypeKind_MetaDescription,
} E2_TypeKind;
C_LINKAGE_BEGIN
extern E2_OpInfo e2_op_kind_info_table[34];
extern E2_OpInfo e2_op_kind_info_table[35];
extern U8 e2_type_kind_basic_byte_size_table[61];
extern String8 e2_type_kind_basic_string_table[61];
+3
View File
@@ -34,6 +34,8 @@
internal void
entry_point(CmdLine *cmdline)
{
E2_ConsTypeMap *cons_types = e2_cons_type_map_alloc();
e2_select_cons_type_map(cons_types);
String8 strings[] =
{
// (A)B
@@ -44,6 +46,7 @@ entry_point(CmdLine *cmdline)
s("123, 456"),
s("int32 == int32"),
s("foo = 123"),
s("bar(a, b) = a + b"),
s("1 > 2"),
s("1 ? \"Test\" : 888"),
s("'a'"),