Tilde: for in for enum types

This commit is contained in:
gingerBill
2023-08-07 14:53:31 +01:00
parent 561a94cc50
commit 8201a9ce6e

View File

@@ -1598,6 +1598,58 @@ gb_internal void cg_build_range_stmt_indexed(cgProcedure *p, cgValue expr, Type
}
gb_internal void cg_build_range_stmt_enum(cgProcedure *p, Type *enum_type, Type *val_type, cgValue *val_, cgValue *idx_, TB_Node **loop_, TB_Node **done_) {
Type *t = enum_type;
GB_ASSERT(is_type_enum(t));
t = base_type(t);
Type *core_elem = core_type(t);
GB_ASSERT(t->kind == Type_Enum);
i64 enum_count = t->Enum.fields.count;
cgValue max_count = cg_const_int(p, t_int, enum_count);
cgValue ti = cg_type_info(p, t);
cgValue variant = cg_emit_struct_ep(p, ti, 4);
cgValue eti_ptr = cg_emit_conv(p, variant, t_type_info_enum_ptr);
cgValue values = cg_emit_load(p, cg_emit_struct_ep(p, eti_ptr, 2));
cgValue values_data = cg_builtin_raw_data(p, values);
cgAddr offset_ = cg_add_local(p, t_int, nullptr, false);
cg_addr_store(p, offset_, cg_const_int(p, t_int, 0));
TB_Node *loop = cg_control_region(p, "for_enum_loop");
cg_emit_goto(p, loop);
tb_inst_set_control(p->func, loop);
TB_Node *body = cg_control_region(p, "for_enum_body");
TB_Node *done = cg_control_region(p, "for_enum_done");
cgValue offset = cg_addr_load(p, offset_);
cgValue cond = cg_emit_comp(p, Token_Lt, offset, max_count);
cg_emit_if(p, cond, body, done);
tb_inst_set_control(p->func, body);
cgValue val_ptr = cg_emit_ptr_offset(p, values_data, offset);
cg_emit_increment(p, offset_.addr);
cgValue val = {};
if (val_type != nullptr) {
GB_ASSERT(are_types_identical(enum_type, val_type));
if (is_type_integer(core_elem)) {
cgValue i = cg_emit_load(p, cg_emit_conv(p, val_ptr, t_i64_ptr));
val = cg_emit_conv(p, i, t);
} else {
GB_PANIC("TODO(bill): enum core type %s", type_to_string(core_elem));
}
}
if (val_) *val_ = val;
if (idx_) *idx_ = offset;
if (loop_) *loop_ = loop;
if (done_) *done_ = done;
}
gb_internal void cg_build_range_stmt(cgProcedure *p, Ast *node) {
ast_node(rs, RangeStmt, node);
@@ -1640,7 +1692,7 @@ gb_internal void cg_build_range_stmt(cgProcedure *p, Ast *node) {
TypeAndValue tav = type_and_value_of_expr(expr);
if (tav.mode == Addressing_Type) {
GB_PANIC("TODO(bill): range statement over enum type");
cg_build_range_stmt_enum(p, type_deref(tav.type), val0_type, &val, &key, &loop, &done);
} else {
Type *expr_type = type_of_expr(expr);
Type *et = base_type(type_deref(expr_type));