| ... | @@ -12447,7 +12447,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12447,7 +12447,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12447 | const payload_val = union_val.val.optionalValue() orelse | 12447 | const payload_val = union_val.val.optionalValue() orelse |
| 12448 | return sema.addType(Type.initTag(.anyerror)); | 12448 | return sema.addType(Type.initTag(.anyerror)); |
| 12449 | const slice_val = payload_val.castTag(.slice).?.data; | 12449 | const slice_val = payload_val.castTag(.slice).?.data; |
| 12450 | const decl = slice_val.ptr.castTag(.decl_ref).?.data; | 12450 | const decl = slice_val.ptr.pointerDecl().?; |
| 12451 | try sema.ensureDeclAnalyzed(decl); | 12451 | try sema.ensureDeclAnalyzed(decl); |
| 12452 | const array_val = decl.val.castTag(.array).?.data; | 12452 | const array_val = decl.val.castTag(.array).?.data; |
| 12453 | | 12453 | |
| ... | @@ -12468,11 +12468,171 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12468,11 +12468,171 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12468 | const ty = try Type.Tag.error_set_merged.create(sema.arena, names); | 12468 | const ty = try Type.Tag.error_set_merged.create(sema.arena, names); |
| 12469 | return sema.addType(ty); | 12469 | return sema.addType(ty); |
| 12470 | }, | 12470 | }, |
| 12471 | .Enum => return sema.fail(block, src, "TODO: Sema.zirReify for Enum", .{}), | 12471 | .Enum => { |
| | 12472 | const struct_val = union_val.val.castTag(.@"struct").?.data; |
| | 12473 | // TODO use reflection instead of magic numbers here |
| | 12474 | // error_set: type, |
| | 12475 | // layout: ContainerLayout, |
| | 12476 | const layout_val = struct_val[0]; |
| | 12477 | // tag_type: type, |
| | 12478 | const tag_type_val = struct_val[1]; |
| | 12479 | // fields: []const EnumField, |
| | 12480 | const fields_val = struct_val[2]; |
| | 12481 | // decls: []const Declaration, |
| | 12482 | const decls_val = struct_val[3]; |
| | 12483 | // is_exhaustive: bool, |
| | 12484 | const is_exhaustive_val = struct_val[4]; |
| | 12485 | |
| | 12486 | // enum layout is always auto |
| | 12487 | const layout = layout_val.toEnum(std.builtin.Type.ContainerLayout); |
| | 12488 | if (layout != .Auto) { |
| | 12489 | return sema.fail(block, src, "reified enums must have a layout .Auto", .{}); |
| | 12490 | } |
| | 12491 | |
| | 12492 | // Decls |
| | 12493 | const decls_slice_val = decls_val.castTag(.slice).?.data; |
| | 12494 | const decls_decl = decls_slice_val.ptr.pointerDecl().?; |
| | 12495 | try sema.ensureDeclAnalyzed(decls_decl); |
| | 12496 | if (decls_decl.ty.arrayLen() > 0) { |
| | 12497 | return sema.fail(block, src, "reified enums must have no decls", .{}); |
| | 12498 | } |
| | 12499 | |
| | 12500 | const mod = sema.mod; |
| | 12501 | const gpa = sema.gpa; |
| | 12502 | var new_decl_arena = std.heap.ArenaAllocator.init(gpa); |
| | 12503 | errdefer new_decl_arena.deinit(); |
| | 12504 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| | 12505 | |
| | 12506 | // Define our empty enum decl |
| | 12507 | const enum_obj = try new_decl_arena_allocator.create(Module.EnumFull); |
| | 12508 | const enum_ty_payload = try new_decl_arena_allocator.create(Type.Payload.EnumFull); |
| | 12509 | enum_ty_payload.* = .{ |
| | 12510 | .base = .{ |
| | 12511 | .tag = if (!is_exhaustive_val.toBool()) |
| | 12512 | .enum_nonexhaustive |
| | 12513 | else |
| | 12514 | .enum_full, |
| | 12515 | }, |
| | 12516 | .data = enum_obj, |
| | 12517 | }; |
| | 12518 | const enum_ty = Type.initPayload(&enum_ty_payload.base); |
| | 12519 | const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty); |
| | 12520 | const type_name = try sema.createTypeName(block, .anon); |
| | 12521 | const new_decl = try mod.createAnonymousDeclNamed(block, .{ |
| | 12522 | .ty = Type.type, |
| | 12523 | .val = enum_val, |
| | 12524 | }, type_name); |
| | 12525 | new_decl.owns_tv = true; |
| | 12526 | errdefer mod.abortAnonDecl(new_decl); |
| | 12527 | |
| | 12528 | enum_obj.* = .{ |
| | 12529 | .owner_decl = new_decl, |
| | 12530 | .tag_ty = Type.initTag(.@"null"), |
| | 12531 | .fields = .{}, |
| | 12532 | .values = .{}, |
| | 12533 | .node_offset = src.node_offset, |
| | 12534 | .namespace = .{ |
| | 12535 | .parent = block.namespace, |
| | 12536 | .ty = enum_ty, |
| | 12537 | .file_scope = block.getFileScope(), |
| | 12538 | }, |
| | 12539 | }; |
| | 12540 | |
| | 12541 | // Enum tag type |
| | 12542 | var buffer: Value.ToTypeBuffer = undefined; |
| | 12543 | enum_obj.tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator); |
| | 12544 | |
| | 12545 | // Fields |
| | 12546 | const slice_val = fields_val.castTag(.slice).?.data; |
| | 12547 | const decl = slice_val.ptr.pointerDecl().?; |
| | 12548 | try sema.ensureDeclAnalyzed(decl); |
| | 12549 | const fields_len = try sema.usizeCast(block, src, decl.ty.arrayLen()); |
| | 12550 | if (fields_len > 0) { |
| | 12551 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| | 12552 | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ |
| | 12553 | .ty = enum_obj.tag_ty, |
| | 12554 | }); |
| | 12555 | |
| | 12556 | const array_vals = decl.val.castTag(.array).?.data; |
| | 12557 | for (array_vals) |elem_val| { |
| | 12558 | const field_struct_val = elem_val.castTag(.@"struct").?.data; |
| | 12559 | // TODO use reflection instead of magic numbers here |
| | 12560 | // name: []const u8 |
| | 12561 | const name_val = field_struct_val[0]; |
| | 12562 | // value: comptime_int |
| | 12563 | const value_val = field_struct_val[1]; |
| | 12564 | |
| | 12565 | const field_name = try name_val.toAllocatedBytes( |
| | 12566 | Type.initTag(.const_slice_u8), |
| | 12567 | new_decl_arena_allocator, |
| | 12568 | ); |
| | 12569 | |
| | 12570 | const gop = enum_obj.fields.getOrPutAssumeCapacity(field_name); |
| | 12571 | if (gop.found_existing) { |
| | 12572 | // TODO: better source location |
| | 12573 | return sema.fail(block, src, "duplicate enum tag {s}", .{field_name}); |
| | 12574 | } |
| | 12575 | |
| | 12576 | const copied_tag_val = try value_val.copy(new_decl_arena_allocator); |
| | 12577 | enum_obj.values.putAssumeCapacityNoClobberContext(copied_tag_val, {}, .{ |
| | 12578 | .ty = enum_obj.tag_ty, |
| | 12579 | }); |
| | 12580 | } |
| | 12581 | } |
| | 12582 | |
| | 12583 | try new_decl.finalizeNewArena(&new_decl_arena); |
| | 12584 | return sema.analyzeDeclVal(block, src, new_decl); |
| | 12585 | }, |
| | 12586 | .Opaque => { |
| | 12587 | const struct_val = union_val.val.castTag(.@"struct").?.data; |
| | 12588 | // decls: []const Declaration, |
| | 12589 | const decls_val = struct_val[0]; |
| | 12590 | |
| | 12591 | // Decls |
| | 12592 | const decls_slice_val = decls_val.castTag(.slice).?.data; |
| | 12593 | const decls_decl = decls_slice_val.ptr.pointerDecl().?; |
| | 12594 | try sema.ensureDeclAnalyzed(decls_decl); |
| | 12595 | if (decls_decl.ty.arrayLen() > 0) { |
| | 12596 | return sema.fail(block, src, "reified opaque must have no decls", .{}); |
| | 12597 | } |
| | 12598 | |
| | 12599 | const mod = sema.mod; |
| | 12600 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| | 12601 | errdefer new_decl_arena.deinit(); |
| | 12602 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| | 12603 | |
| | 12604 | const opaque_obj = try new_decl_arena_allocator.create(Module.Opaque); |
| | 12605 | const opaque_ty_payload = try new_decl_arena_allocator.create(Type.Payload.Opaque); |
| | 12606 | opaque_ty_payload.* = .{ |
| | 12607 | .base = .{ .tag = .@"opaque" }, |
| | 12608 | .data = opaque_obj, |
| | 12609 | }; |
| | 12610 | const opaque_ty = Type.initPayload(&opaque_ty_payload.base); |
| | 12611 | const opaque_val = try Value.Tag.ty.create(new_decl_arena_allocator, opaque_ty); |
| | 12612 | const type_name = try sema.createTypeName(block, .anon); |
| | 12613 | const new_decl = try mod.createAnonymousDeclNamed(block, .{ |
| | 12614 | .ty = Type.type, |
| | 12615 | .val = opaque_val, |
| | 12616 | }, type_name); |
| | 12617 | new_decl.owns_tv = true; |
| | 12618 | errdefer mod.abortAnonDecl(new_decl); |
| | 12619 | |
| | 12620 | opaque_obj.* = .{ |
| | 12621 | .owner_decl = new_decl, |
| | 12622 | .node_offset = src.node_offset, |
| | 12623 | .namespace = .{ |
| | 12624 | .parent = block.namespace, |
| | 12625 | .ty = opaque_ty, |
| | 12626 | .file_scope = block.getFileScope(), |
| | 12627 | }, |
| | 12628 | }; |
| | 12629 | |
| | 12630 | try new_decl.finalizeNewArena(&new_decl_arena); |
| | 12631 | return sema.analyzeDeclVal(block, src, new_decl); |
| | 12632 | }, |
| 12472 | .Union => return sema.fail(block, src, "TODO: Sema.zirReify for Union", .{}), | 12633 | .Union => return sema.fail(block, src, "TODO: Sema.zirReify for Union", .{}), |
| 12473 | .Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}), | 12634 | .Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}), |
| 12474 | .BoundFn => @panic("TODO delete BoundFn from the language"), | 12635 | .BoundFn => @panic("TODO delete BoundFn from the language"), |
| 12475 | .Opaque => return sema.fail(block, src, "TODO: Sema.zirReify for Opaque", .{}), | | |
| 12476 | .Frame => return sema.fail(block, src, "TODO: Sema.zirReify for Frame", .{}), | 12636 | .Frame => return sema.fail(block, src, "TODO: Sema.zirReify for Frame", .{}), |
| 12477 | } | 12637 | } |
| 12478 | } | 12638 | } |