diff --git a/src/eval/eval.mdesk b/src/eval/eval.mdesk index 05737d53..ffb12495 100644 --- a/src/eval/eval.mdesk +++ b/src/eval/eval.mdesk @@ -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) diff --git a/src/eval/eval_ir.c b/src/eval/eval_ir.c index 55610b1a..766675e7 100644 --- a/src/eval/eval_ir.c +++ b/src/eval/eval_ir.c @@ -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; } diff --git a/src/eval/eval_ir.h b/src/eval/eval_ir.h index eef75238..3bbb6f63 100644 --- a/src/eval/eval_ir.h +++ b/src/eval/eval_ir.h @@ -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); diff --git a/src/eval/eval_parse.c b/src/eval/eval_parse.c index 60f31be4..12e4ea03 100644 --- a/src/eval/eval_parse.c +++ b/src/eval/eval_parse.c @@ -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) { diff --git a/src/eval/eval_parse.h b/src/eval/eval_parse.h index 9f46e6f7..f4ee3afe 100644 --- a/src/eval/eval_parse.h +++ b/src/eval/eval_parse.h @@ -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 diff --git a/src/eval/generated/eval.meta.c b/src/eval/generated/eval.meta.c index eec6b7bc..673119c9 100644 --- a/src/eval/generated/eval.meta.c +++ b/src/eval/generated/eval.meta.c @@ -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] = diff --git a/src/eval/generated/eval.meta.h b/src/eval/generated/eval.meta.h index 125d8245..f227b316 100644 --- a/src/eval/generated/eval.meta.h +++ b/src/eval/generated/eval.meta.h @@ -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];