| ... | @@ -12459,7 +12459,6 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12459,7 +12459,6 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12459 | const ty = try Type.array(sema.arena, len, sentinel, child_ty); | 12459 | const ty = try Type.array(sema.arena, len, sentinel, child_ty); |
| 12460 | return sema.addType(ty); | 12460 | return sema.addType(ty); |
| 12461 | }, | 12461 | }, |
| 12462 | .Struct => return sema.fail(block, src, "TODO: Sema.zirReify for Struct", .{}), | | |
| 12463 | .Optional => { | 12462 | .Optional => { |
| 12464 | const struct_val = union_val.val.castTag(.@"struct").?.data; | 12463 | const struct_val = union_val.val.castTag(.@"struct").?.data; |
| 12465 | // TODO use reflection instead of magic numbers here | 12464 | // TODO use reflection instead of magic numbers here |
| ... | @@ -12515,10 +12514,31 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12515,10 +12514,31 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12515 | const ty = try Type.Tag.error_set_merged.create(sema.arena, names); | 12514 | const ty = try Type.Tag.error_set_merged.create(sema.arena, names); |
| 12516 | return sema.addType(ty); | 12515 | return sema.addType(ty); |
| 12517 | }, | 12516 | }, |
| | 12517 | .Struct => { |
| | 12518 | // TODO use reflection instead of magic numbers here |
| | 12519 | const struct_val = union_val.val.castTag(.@"struct").?.data; |
| | 12520 | // layout: containerlayout, |
| | 12521 | const layout_val = struct_val[0]; |
| | 12522 | // fields: []const enumfield, |
| | 12523 | const fields_val = struct_val[1]; |
| | 12524 | // decls: []const declaration, |
| | 12525 | const decls_val = struct_val[2]; |
| | 12526 | // is_tuple: bool, |
| | 12527 | const is_tuple_val = struct_val[3]; |
| | 12528 | |
| | 12529 | // Decls |
| | 12530 | if (decls_val.sliceLen() > 0) { |
| | 12531 | return sema.fail(block, src, "reified structs must have no decls", .{}); |
| | 12532 | } |
| | 12533 | |
| | 12534 | return if (is_tuple_val.toBool()) |
| | 12535 | try sema.reifyTuple(block, src, fields_val) |
| | 12536 | else |
| | 12537 | try sema.reifyStruct(block, inst, src, layout_val, fields_val); |
| | 12538 | }, |
| 12518 | .Enum => { | 12539 | .Enum => { |
| 12519 | const struct_val = union_val.val.castTag(.@"struct").?.data; | 12540 | const struct_val = union_val.val.castTag(.@"struct").?.data; |
| 12520 | // TODO use reflection instead of magic numbers here | 12541 | // TODO use reflection instead of magic numbers here |
| 12521 | // error_set: type, | | |
| 12522 | // layout: ContainerLayout, | 12542 | // layout: ContainerLayout, |
| 12523 | const layout_val = struct_val[0]; | 12543 | const layout_val = struct_val[0]; |
| 12524 | // tag_type: type, | 12544 | // tag_type: type, |
| ... | @@ -12537,10 +12557,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12537,10 +12557,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12537 | } | 12557 | } |
| 12538 | | 12558 | |
| 12539 | // Decls | 12559 | // Decls |
| 12540 | const decls_slice_val = decls_val.castTag(.slice).?.data; | 12560 | if (decls_val.sliceLen() > 0) { |
| 12541 | const decls_decl = decls_slice_val.ptr.pointerDecl().?; | | |
| 12542 | try sema.ensureDeclAnalyzed(decls_decl); | | |
| 12543 | if (decls_decl.ty.arrayLen() > 0) { | | |
| 12544 | return sema.fail(block, src, "reified enums must have no decls", .{}); | 12561 | return sema.fail(block, src, "reified enums must have no decls", .{}); |
| 12545 | } | 12562 | } |
| 12546 | | 12563 | |
| ... | @@ -12636,10 +12653,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12636,10 +12653,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12636 | const decls_val = struct_val[0]; | 12653 | const decls_val = struct_val[0]; |
| 12637 | | 12654 | |
| 12638 | // Decls | 12655 | // Decls |
| 12639 | const decls_slice_val = decls_val.castTag(.slice).?.data; | 12656 | if (decls_val.sliceLen() > 0) { |
| 12640 | const decls_decl = decls_slice_val.ptr.pointerDecl().?; | | |
| 12641 | try sema.ensureDeclAnalyzed(decls_decl); | | |
| 12642 | if (decls_decl.ty.arrayLen() > 0) { | | |
| 12643 | return sema.fail(block, src, "reified opaque must have no decls", .{}); | 12657 | return sema.fail(block, src, "reified opaque must have no decls", .{}); |
| 12644 | } | 12658 | } |
| 12645 | | 12659 | |
| ... | @@ -12684,6 +12698,172 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12684,6 +12698,172 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12684 | } | 12698 | } |
| 12685 | } | 12699 | } |
| 12686 | | 12700 | |
| | 12701 | fn reifyTuple( |
| | 12702 | sema: *Sema, |
| | 12703 | block: *Block, |
| | 12704 | src: LazySrcLoc, |
| | 12705 | fields_val: Value, |
| | 12706 | ) CompileError!Air.Inst.Ref { |
| | 12707 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen()); |
| | 12708 | if (fields_len == 0) return sema.addType(Type.initTag(.empty_struct_literal)); |
| | 12709 | |
| | 12710 | const types = try sema.arena.alloc(Type, fields_len); |
| | 12711 | const values = try sema.arena.alloc(Value, fields_len); |
| | 12712 | |
| | 12713 | var used_fields: std.AutoArrayHashMapUnmanaged(u32, void) = .{}; |
| | 12714 | defer used_fields.deinit(sema.gpa); |
| | 12715 | try used_fields.ensureTotalCapacity(sema.gpa, fields_len); |
| | 12716 | |
| | 12717 | var i: usize = 0; |
| | 12718 | while (i < fields_len) : (i += 1) { |
| | 12719 | const elem_val = try fields_val.elemValue(sema.arena, i); |
| | 12720 | const field_struct_val = elem_val.castTag(.@"struct").?.data; |
| | 12721 | // TODO use reflection instead of magic numbers here |
| | 12722 | // name: []const u8 |
| | 12723 | const name_val = field_struct_val[0]; |
| | 12724 | // field_type: type, |
| | 12725 | const field_type_val = field_struct_val[1]; |
| | 12726 | //default_value: ?*const anyopaque, |
| | 12727 | const default_value_val = field_struct_val[2]; |
| | 12728 | |
| | 12729 | const field_name = try name_val.toAllocatedBytes( |
| | 12730 | Type.initTag(.const_slice_u8), |
| | 12731 | sema.arena, |
| | 12732 | ); |
| | 12733 | |
| | 12734 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { |
| | 12735 | return sema.fail( |
| | 12736 | block, |
| | 12737 | src, |
| | 12738 | "tuple cannot have non-numeric field '{s}': {}", |
| | 12739 | .{ field_name, err }, |
| | 12740 | ); |
| | 12741 | }; |
| | 12742 | |
| | 12743 | if (field_index >= fields_len) { |
| | 12744 | return sema.fail( |
| | 12745 | block, |
| | 12746 | src, |
| | 12747 | "tuple field {} exceeds tuple field count", |
| | 12748 | .{field_index}, |
| | 12749 | ); |
| | 12750 | } |
| | 12751 | |
| | 12752 | const gop = used_fields.getOrPutAssumeCapacity(field_index); |
| | 12753 | if (gop.found_existing) { |
| | 12754 | // TODO: better source location |
| | 12755 | return sema.fail(block, src, "duplicate tuple field {}", .{field_index}); |
| | 12756 | } |
| | 12757 | |
| | 12758 | const default_val = if (default_value_val.optionalValue()) |opt_val| blk: { |
| | 12759 | const payload_val = if (opt_val.pointerDecl()) |opt_decl| |
| | 12760 | opt_decl.val |
| | 12761 | else |
| | 12762 | opt_val; |
| | 12763 | break :blk try payload_val.copy(sema.arena); |
| | 12764 | } else Value.initTag(.unreachable_value); |
| | 12765 | |
| | 12766 | var buffer: Value.ToTypeBuffer = undefined; |
| | 12767 | types[field_index] = try field_type_val.toType(&buffer).copy(sema.arena); |
| | 12768 | values[field_index] = default_val; |
| | 12769 | } |
| | 12770 | |
| | 12771 | const ty = try Type.Tag.tuple.create(sema.arena, .{ |
| | 12772 | .types = types, |
| | 12773 | .values = values, |
| | 12774 | }); |
| | 12775 | return sema.addType(ty); |
| | 12776 | } |
| | 12777 | |
| | 12778 | fn reifyStruct( |
| | 12779 | sema: *Sema, |
| | 12780 | block: *Block, |
| | 12781 | inst: Zir.Inst.Index, |
| | 12782 | src: LazySrcLoc, |
| | 12783 | layout_val: Value, |
| | 12784 | fields_val: Value, |
| | 12785 | ) CompileError!Air.Inst.Ref { |
| | 12786 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| | 12787 | errdefer new_decl_arena.deinit(); |
| | 12788 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| | 12789 | |
| | 12790 | const struct_obj = try new_decl_arena_allocator.create(Module.Struct); |
| | 12791 | const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj); |
| | 12792 | const new_struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty); |
| | 12793 | const type_name = try sema.createTypeName(block, .anon); |
| | 12794 | const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ |
| | 12795 | .ty = Type.type, |
| | 12796 | .val = new_struct_val, |
| | 12797 | }, type_name); |
| | 12798 | new_decl.owns_tv = true; |
| | 12799 | errdefer sema.mod.abortAnonDecl(new_decl); |
| | 12800 | struct_obj.* = .{ |
| | 12801 | .owner_decl = new_decl, |
| | 12802 | .fields = .{}, |
| | 12803 | .node_offset = src.node_offset, |
| | 12804 | .zir_index = inst, |
| | 12805 | .layout = layout_val.toEnum(std.builtin.Type.ContainerLayout), |
| | 12806 | .status = .have_field_types, |
| | 12807 | .known_non_opv = undefined, |
| | 12808 | .namespace = .{ |
| | 12809 | .parent = block.namespace, |
| | 12810 | .ty = struct_ty, |
| | 12811 | .file_scope = block.getFileScope(), |
| | 12812 | }, |
| | 12813 | }; |
| | 12814 | |
| | 12815 | // Fields |
| | 12816 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen()); |
| | 12817 | try struct_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| | 12818 | var i: usize = 0; |
| | 12819 | while (i < fields_len) : (i += 1) { |
| | 12820 | const elem_val = try fields_val.elemValue(sema.arena, i); |
| | 12821 | const field_struct_val = elem_val.castTag(.@"struct").?.data; |
| | 12822 | // TODO use reflection instead of magic numbers here |
| | 12823 | // name: []const u8 |
| | 12824 | const name_val = field_struct_val[0]; |
| | 12825 | // field_type: type, |
| | 12826 | const field_type_val = field_struct_val[1]; |
| | 12827 | //default_value: ?*const anyopaque, |
| | 12828 | const default_value_val = field_struct_val[2]; |
| | 12829 | // is_comptime: bool, |
| | 12830 | const is_comptime_val = field_struct_val[3]; |
| | 12831 | // alignment: comptime_int, |
| | 12832 | const alignment_val = field_struct_val[4]; |
| | 12833 | |
| | 12834 | const field_name = try name_val.toAllocatedBytes( |
| | 12835 | Type.initTag(.const_slice_u8), |
| | 12836 | new_decl_arena_allocator, |
| | 12837 | ); |
| | 12838 | |
| | 12839 | const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name); |
| | 12840 | if (gop.found_existing) { |
| | 12841 | // TODO: better source location |
| | 12842 | return sema.fail(block, src, "duplicate struct field {s}", .{field_name}); |
| | 12843 | } |
| | 12844 | |
| | 12845 | const default_val = if (default_value_val.optionalValue()) |opt_val| blk: { |
| | 12846 | const payload_val = if (opt_val.pointerDecl()) |opt_decl| |
| | 12847 | opt_decl.val |
| | 12848 | else |
| | 12849 | opt_val; |
| | 12850 | break :blk try payload_val.copy(new_decl_arena_allocator); |
| | 12851 | } else Value.initTag(.unreachable_value); |
| | 12852 | |
| | 12853 | var buffer: Value.ToTypeBuffer = undefined; |
| | 12854 | gop.value_ptr.* = .{ |
| | 12855 | .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator), |
| | 12856 | .abi_align = try alignment_val.copy(new_decl_arena_allocator), |
| | 12857 | .default_val = default_val, |
| | 12858 | .is_comptime = is_comptime_val.toBool(), |
| | 12859 | .offset = undefined, |
| | 12860 | }; |
| | 12861 | } |
| | 12862 | |
| | 12863 | try new_decl.finalizeNewArena(&new_decl_arena); |
| | 12864 | return sema.analyzeDeclVal(block, src, new_decl); |
| | 12865 | } |
| | 12866 | |
| 12687 | fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 12867 | fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 12688 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 12868 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 12689 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 12869 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |