| ... | @@ -112,18 +112,39 @@ pub const Type = extern union { | ... | @@ -112,18 +112,39 @@ pub const Type = extern union { |
| 112 | } | 112 | } |
| 113 | } | 113 | } |
| 114 | | 114 | |
| | 115 | /// Prefer `castTag` to this. |
| 115 | pub fn cast(self: Type, comptime T: type) ?*T { | 116 | pub fn cast(self: Type, comptime T: type) ?*T { |
| 116 | if (self.tag_if_small_enough < Tag.no_payload_count) | 117 | if (@hasField(T, "base_tag")) { |
| | 118 | return base.castTag(T.base_tag); |
| | 119 | } |
| | 120 | if (self.tag_if_small_enough < Tag.no_payload_count) { |
| 117 | return null; | 121 | return null; |
| | 122 | } |
| | 123 | inline for (@typeInfo(Tag).Enum.fields) |field| { |
| | 124 | if (field.value < Tag.no_payload_count) |
| | 125 | continue; |
| | 126 | const t = @intToEnum(Tag, field.value); |
| | 127 | if (self.ptr_otherwise.tag == t) { |
| | 128 | if (T == t.Type()) { |
| | 129 | return @fieldParentPtr(T, "base", self.ptr_otherwise); |
| | 130 | } |
| | 131 | return null; |
| | 132 | } |
| | 133 | } |
| | 134 | unreachable; |
| | 135 | } |
| 118 | | 136 | |
| 119 | const expected_tag = std.meta.fieldInfo(T, "base").default_value.?.tag; | 137 | pub fn castTag(self: Type, comptime t: Tag) ?*t.Type() { |
| 120 | if (self.ptr_otherwise.tag != expected_tag) | 138 | if (self.tag_if_small_enough < Tag.no_payload_count) |
| 121 | return null; | 139 | return null; |
| 122 | | 140 | |
| 123 | return @fieldParentPtr(T, "base", self.ptr_otherwise); | 141 | if (self.ptr_otherwise.tag == t) |
| | 142 | return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise); |
| | 143 | |
| | 144 | return null; |
| 124 | } | 145 | } |
| 125 | | 146 | |
| 126 | pub fn castPointer(self: Type) ?*Payload.PointerSimple { | 147 | pub fn castPointer(self: Type) ?*Payload.ElemType { |
| 127 | return switch (self.tag()) { | 148 | return switch (self.tag()) { |
| 128 | .single_const_pointer, | 149 | .single_const_pointer, |
| 129 | .single_mut_pointer, | 150 | .single_mut_pointer, |
| ... | @@ -135,7 +156,8 @@ pub const Type = extern union { | ... | @@ -135,7 +156,8 @@ pub const Type = extern union { |
| 135 | .mut_slice, | 156 | .mut_slice, |
| 136 | .optional_single_const_pointer, | 157 | .optional_single_const_pointer, |
| 137 | .optional_single_mut_pointer, | 158 | .optional_single_mut_pointer, |
| 138 | => @fieldParentPtr(Payload.PointerSimple, "base", self.ptr_otherwise), | 159 | => self.cast(Payload.ElemType), |
| | 160 | |
| 139 | else => null, | 161 | else => null, |
| 140 | }; | 162 | }; |
| 141 | } | 163 | } |
| ... | @@ -165,7 +187,7 @@ pub const Type = extern union { | ... | @@ -165,7 +187,7 @@ pub const Type = extern union { |
| 165 | // Hot path for common case: | 187 | // Hot path for common case: |
| 166 | if (a.castPointer()) |a_payload| { | 188 | if (a.castPointer()) |a_payload| { |
| 167 | if (b.castPointer()) |b_payload| { | 189 | if (b.castPointer()) |b_payload| { |
| 168 | return a.tag() == b.tag() and eql(a_payload.pointee_type, b_payload.pointee_type); | 190 | return a.tag() == b.tag() and eql(a_payload.data, b_payload.data); |
| 169 | } | 191 | } |
| 170 | } | 192 | } |
| 171 | const is_slice_a = isSlice(a); | 193 | const is_slice_a = isSlice(a); |
| ... | @@ -230,8 +252,8 @@ pub const Type = extern union { | ... | @@ -230,8 +252,8 @@ pub const Type = extern union { |
| 230 | return true; | 252 | return true; |
| 231 | }, | 253 | }, |
| 232 | .Optional => { | 254 | .Optional => { |
| 233 | var buf_a: Payload.PointerSimple = undefined; | 255 | var buf_a: Payload.ElemType = undefined; |
| 234 | var buf_b: Payload.PointerSimple = undefined; | 256 | var buf_b: Payload.ElemType = undefined; |
| 235 | return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b)); | 257 | return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b)); |
| 236 | }, | 258 | }, |
| 237 | .Float, | 259 | .Float, |
| ... | @@ -294,7 +316,7 @@ pub const Type = extern union { | ... | @@ -294,7 +316,7 @@ pub const Type = extern union { |
| 294 | } | 316 | } |
| 295 | }, | 317 | }, |
| 296 | .Optional => { | 318 | .Optional => { |
| 297 | var buf: Payload.PointerSimple = undefined; | 319 | var buf: Payload.ElemType = undefined; |
| 298 | std.hash.autoHash(&hasher, self.optionalChild(&buf).hash()); | 320 | std.hash.autoHash(&hasher, self.optionalChild(&buf).hash()); |
| 299 | }, | 321 | }, |
| 300 | .Float, | 322 | .Float, |
| ... | @@ -364,68 +386,64 @@ pub const Type = extern union { | ... | @@ -364,68 +386,64 @@ pub const Type = extern union { |
| 364 | .@"anyframe", | 386 | .@"anyframe", |
| 365 | => unreachable, | 387 | => unreachable, |
| 366 | | 388 | |
| 367 | .array_u8_sentinel_0 => return self.copyPayloadShallow(allocator, Payload.Array_u8_Sentinel0), | 389 | .array_u8, |
| 368 | .array_u8 => return self.copyPayloadShallow(allocator, Payload.Array_u8), | 390 | .array_u8_sentinel_0, |
| | 391 | => return self.copyPayloadShallow(allocator, Payload.Len), |
| | 392 | |
| | 393 | .single_const_pointer, |
| | 394 | .single_mut_pointer, |
| | 395 | .many_const_pointer, |
| | 396 | .many_mut_pointer, |
| | 397 | .c_const_pointer, |
| | 398 | .c_mut_pointer, |
| | 399 | .const_slice, |
| | 400 | .mut_slice, |
| | 401 | .optional, |
| | 402 | .optional_single_mut_pointer, |
| | 403 | .optional_single_const_pointer, |
| | 404 | .anyframe_T, |
| | 405 | => return self.copyPayloadShallow(allocator, Payload.ElemType), |
| | 406 | |
| | 407 | .int_signed, |
| | 408 | .int_unsigned, |
| | 409 | => return self.copyPayloadShallow(allocator, Payload.Bits), |
| | 410 | |
| 369 | .array => { | 411 | .array => { |
| 370 | const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise); | 412 | const payload = self.castTag(.array).?.data; |
| 371 | const new_payload = try allocator.create(Payload.Array); | 413 | return Tag.array.create(allocator, .{ |
| 372 | new_payload.* = .{ | | |
| 373 | .base = payload.base, | | |
| 374 | .len = payload.len, | 414 | .len = payload.len, |
| 375 | .elem_type = try payload.elem_type.copy(allocator), | 415 | .elem_type = try payload.elem_type.copy(allocator), |
| 376 | }; | 416 | }); |
| 377 | return Type{ .ptr_otherwise = &new_payload.base }; | | |
| 378 | }, | 417 | }, |
| 379 | .array_sentinel => { | 418 | .array_sentinel => { |
| 380 | const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise); | 419 | const payload = self.castTag(.array_sentinel).?.data; |
| 381 | const new_payload = try allocator.create(Payload.ArraySentinel); | 420 | return Tag.array_sentinel.create(allocator, .{ |
| 382 | new_payload.* = .{ | | |
| 383 | .base = payload.base, | | |
| 384 | .len = payload.len, | 421 | .len = payload.len, |
| 385 | .sentinel = try payload.sentinel.copy(allocator), | 422 | .sentinel = try payload.sentinel.copy(allocator), |
| 386 | .elem_type = try payload.elem_type.copy(allocator), | 423 | .elem_type = try payload.elem_type.copy(allocator), |
| 387 | }; | 424 | }); |
| 388 | return Type{ .ptr_otherwise = &new_payload.base }; | | |
| 389 | }, | 425 | }, |
| 390 | .int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned), | | |
| 391 | .int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned), | | |
| 392 | .function => { | 426 | .function => { |
| 393 | const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise); | 427 | const payload = self.castTag(.function).?.data; |
| 394 | const new_payload = try allocator.create(Payload.Function); | | |
| 395 | const param_types = try allocator.alloc(Type, payload.param_types.len); | 428 | const param_types = try allocator.alloc(Type, payload.param_types.len); |
| 396 | for (payload.param_types) |param_type, i| { | 429 | for (payload.param_types) |param_type, i| { |
| 397 | param_types[i] = try param_type.copy(allocator); | 430 | param_types[i] = try param_type.copy(allocator); |
| 398 | } | 431 | } |
| 399 | new_payload.* = .{ | 432 | return Tag.function.create(allocator, .{ |
| 400 | .base = payload.base, | | |
| 401 | .return_type = try payload.return_type.copy(allocator), | 433 | .return_type = try payload.return_type.copy(allocator), |
| 402 | .param_types = param_types, | 434 | .param_types = param_types, |
| 403 | .cc = payload.cc, | 435 | .cc = payload.cc, |
| 404 | }; | 436 | }); |
| 405 | return Type{ .ptr_otherwise = &new_payload.base }; | | |
| 406 | }, | 437 | }, |
| 407 | .optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"), | | |
| 408 | .single_const_pointer, | | |
| 409 | .single_mut_pointer, | | |
| 410 | .many_const_pointer, | | |
| 411 | .many_mut_pointer, | | |
| 412 | .c_const_pointer, | | |
| 413 | .c_mut_pointer, | | |
| 414 | .const_slice, | | |
| 415 | .mut_slice, | | |
| 416 | .optional_single_mut_pointer, | | |
| 417 | .optional_single_const_pointer, | | |
| 418 | => return self.copyPayloadSingleField(allocator, Payload.PointerSimple, "pointee_type"), | | |
| 419 | .anyframe_T => return self.copyPayloadSingleField(allocator, Payload.AnyFrame, "return_type"), | | |
| 420 | | | |
| 421 | .pointer => { | 438 | .pointer => { |
| 422 | const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); | 439 | const payload = self.castTag(.pointer).?.data; |
| 423 | const new_payload = try allocator.create(Payload.Pointer); | 440 | const sent: ?Value = if (payload.sentinel) |some| |
| 424 | new_payload.* = .{ | 441 | try some.copy(allocator) |
| 425 | .base = payload.base, | 442 | else |
| 426 | | 443 | null; |
| | 444 | return Tag.pointer.create(allocator, .{ |
| 427 | .pointee_type = try payload.pointee_type.copy(allocator), | 445 | .pointee_type = try payload.pointee_type.copy(allocator), |
| 428 | .sentinel = if (payload.sentinel) |some| try some.copy(allocator) else null, | 446 | .sentinel = sent, |
| 429 | .@"align" = payload.@"align", | 447 | .@"align" = payload.@"align", |
| 430 | .bit_offset = payload.bit_offset, | 448 | .bit_offset = payload.bit_offset, |
| 431 | .host_size = payload.host_size, | 449 | .host_size = payload.host_size, |
| ... | @@ -433,41 +451,28 @@ pub const Type = extern union { | ... | @@ -433,41 +451,28 @@ pub const Type = extern union { |
| 433 | .mutable = payload.mutable, | 451 | .mutable = payload.mutable, |
| 434 | .@"volatile" = payload.@"volatile", | 452 | .@"volatile" = payload.@"volatile", |
| 435 | .size = payload.size, | 453 | .size = payload.size, |
| 436 | }; | 454 | }); |
| 437 | return Type{ .ptr_otherwise = &new_payload.base }; | | |
| 438 | }, | 455 | }, |
| 439 | .error_union => { | 456 | .error_union => { |
| 440 | const payload = @fieldParentPtr(Payload.ErrorUnion, "base", self.ptr_otherwise); | 457 | const payload = self.castTag(.error_union).?.data; |
| 441 | const new_payload = try allocator.create(Payload.ErrorUnion); | 458 | return Tag.error_union.create(allocator, .{ |
| 442 | new_payload.* = .{ | | |
| 443 | .base = payload.base, | | |
| 444 | | | |
| 445 | .error_set = try payload.error_set.copy(allocator), | 459 | .error_set = try payload.error_set.copy(allocator), |
| 446 | .payload = try payload.payload.copy(allocator), | 460 | .payload = try payload.payload.copy(allocator), |
| 447 | }; | 461 | }); |
| 448 | return Type{ .ptr_otherwise = &new_payload.base }; | | |
| 449 | }, | 462 | }, |
| 450 | .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet), | 463 | .error_set => return self.copyPayloadShallow(allocator, Payload.Decl), |
| 451 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.ErrorSetSingle), | 464 | .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name), |
| 452 | .empty_struct => return self.copyPayloadShallow(allocator, Payload.EmptyStruct), | 465 | .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope), |
| 453 | } | 466 | } |
| 454 | } | 467 | } |
| 455 | | 468 | |
| 456 | fn copyPayloadShallow(self: Type, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Type { | 469 | fn copyPayloadShallow(self: Type, allocator: *Allocator, comptime T: type) error{OutOfMemory}!Type { |
| 457 | const payload = @fieldParentPtr(T, "base", self.ptr_otherwise); | 470 | const payload = self.cast(T).?; |
| 458 | const new_payload = try allocator.create(T); | 471 | const new_payload = try allocator.create(T); |
| 459 | new_payload.* = payload.*; | 472 | new_payload.* = payload.*; |
| 460 | return Type{ .ptr_otherwise = &new_payload.base }; | 473 | return Type{ .ptr_otherwise = &new_payload.base }; |
| 461 | } | 474 | } |
| 462 | | 475 | |
| 463 | fn copyPayloadSingleField(self: Type, allocator: *Allocator, comptime T: type, comptime field_name: []const u8) error{OutOfMemory}!Type { | | |
| 464 | const payload = @fieldParentPtr(T, "base", self.ptr_otherwise); | | |
| 465 | const new_payload = try allocator.create(T); | | |
| 466 | new_payload.base = payload.base; | | |
| 467 | @field(new_payload, field_name) = try @field(payload, field_name).copy(allocator); | | |
| 468 | return Type{ .ptr_otherwise = &new_payload.base }; | | |
| 469 | } | | |
| 470 | | | |
| 471 | pub fn format( | 476 | pub fn format( |
| 472 | self: Type, | 477 | self: Type, |
| 473 | comptime fmt: []const u8, | 478 | comptime fmt: []const u8, |
| ... | @@ -527,7 +532,7 @@ pub const Type = extern union { | ... | @@ -527,7 +532,7 @@ pub const Type = extern union { |
| 527 | .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"), | 532 | .fn_ccc_void_no_args => return out_stream.writeAll("fn() callconv(.C) void"), |
| 528 | .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"), | 533 | .single_const_pointer_to_comptime_int => return out_stream.writeAll("*const comptime_int"), |
| 529 | .function => { | 534 | .function => { |
| 530 | const payload = @fieldParentPtr(Payload.Function, "base", ty.ptr_otherwise); | 535 | const payload = ty.castTag(.function).?.data; |
| 531 | try out_stream.writeAll("fn("); | 536 | try out_stream.writeAll("fn("); |
| 532 | for (payload.param_types) |param_type, i| { | 537 | for (payload.param_types) |param_type, i| { |
| 533 | if (i != 0) try out_stream.writeAll(", "); | 538 | if (i != 0) try out_stream.writeAll(", "); |
| ... | @@ -539,108 +544,108 @@ pub const Type = extern union { | ... | @@ -539,108 +544,108 @@ pub const Type = extern union { |
| 539 | }, | 544 | }, |
| 540 | | 545 | |
| 541 | .anyframe_T => { | 546 | .anyframe_T => { |
| 542 | const payload = @fieldParentPtr(Payload.AnyFrame, "base", ty.ptr_otherwise); | 547 | const return_type = ty.castTag(.anyframe_T).?.data; |
| 543 | try out_stream.print("anyframe->", .{}); | 548 | try out_stream.print("anyframe->", .{}); |
| 544 | ty = payload.return_type; | 549 | ty = return_type; |
| 545 | continue; | 550 | continue; |
| 546 | }, | 551 | }, |
| 547 | .array_u8 => { | 552 | .array_u8 => { |
| 548 | const payload = @fieldParentPtr(Payload.Array_u8, "base", ty.ptr_otherwise); | 553 | const len = ty.castTag(.array_u8).?.data; |
| 549 | return out_stream.print("[{}]u8", .{payload.len}); | 554 | return out_stream.print("[{}]u8", .{len}); |
| 550 | }, | 555 | }, |
| 551 | .array_u8_sentinel_0 => { | 556 | .array_u8_sentinel_0 => { |
| 552 | const payload = @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", ty.ptr_otherwise); | 557 | const len = ty.castTag(.array_u8_sentinel_0).?.data; |
| 553 | return out_stream.print("[{}:0]u8", .{payload.len}); | 558 | return out_stream.print("[{}:0]u8", .{len}); |
| 554 | }, | 559 | }, |
| 555 | .array => { | 560 | .array => { |
| 556 | const payload = @fieldParentPtr(Payload.Array, "base", ty.ptr_otherwise); | 561 | const payload = ty.castTag(.array).?.data; |
| 557 | try out_stream.print("[{}]", .{payload.len}); | 562 | try out_stream.print("[{}]", .{payload.len}); |
| 558 | ty = payload.elem_type; | 563 | ty = payload.elem_type; |
| 559 | continue; | 564 | continue; |
| 560 | }, | 565 | }, |
| 561 | .array_sentinel => { | 566 | .array_sentinel => { |
| 562 | const payload = @fieldParentPtr(Payload.ArraySentinel, "base", ty.ptr_otherwise); | 567 | const payload = ty.castTag(.array_sentinel).?.data; |
| 563 | try out_stream.print("[{}:{}]", .{ payload.len, payload.sentinel }); | 568 | try out_stream.print("[{}:{}]", .{ payload.len, payload.sentinel }); |
| 564 | ty = payload.elem_type; | 569 | ty = payload.elem_type; |
| 565 | continue; | 570 | continue; |
| 566 | }, | 571 | }, |
| 567 | .single_const_pointer => { | 572 | .single_const_pointer => { |
| 568 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 573 | const pointee_type = ty.castTag(.single_const_pointer).?.data; |
| 569 | try out_stream.writeAll("*const "); | 574 | try out_stream.writeAll("*const "); |
| 570 | ty = payload.pointee_type; | 575 | ty = pointee_type; |
| 571 | continue; | 576 | continue; |
| 572 | }, | 577 | }, |
| 573 | .single_mut_pointer => { | 578 | .single_mut_pointer => { |
| 574 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 579 | const pointee_type = ty.castTag(.single_mut_pointer).?.data; |
| 575 | try out_stream.writeAll("*"); | 580 | try out_stream.writeAll("*"); |
| 576 | ty = payload.pointee_type; | 581 | ty = pointee_type; |
| 577 | continue; | 582 | continue; |
| 578 | }, | 583 | }, |
| 579 | .many_const_pointer => { | 584 | .many_const_pointer => { |
| 580 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 585 | const pointee_type = ty.castTag(.many_const_pointer).?.data; |
| 581 | try out_stream.writeAll("[*]const "); | 586 | try out_stream.writeAll("[*]const "); |
| 582 | ty = payload.pointee_type; | 587 | ty = pointee_type; |
| 583 | continue; | 588 | continue; |
| 584 | }, | 589 | }, |
| 585 | .many_mut_pointer => { | 590 | .many_mut_pointer => { |
| 586 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 591 | const pointee_type = ty.castTag(.many_mut_pointer).?.data; |
| 587 | try out_stream.writeAll("[*]"); | 592 | try out_stream.writeAll("[*]"); |
| 588 | ty = payload.pointee_type; | 593 | ty = pointee_type; |
| 589 | continue; | 594 | continue; |
| 590 | }, | 595 | }, |
| 591 | .c_const_pointer => { | 596 | .c_const_pointer => { |
| 592 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 597 | const pointee_type = ty.castTag(.c_const_pointer).?.data; |
| 593 | try out_stream.writeAll("[*c]const "); | 598 | try out_stream.writeAll("[*c]const "); |
| 594 | ty = payload.pointee_type; | 599 | ty = pointee_type; |
| 595 | continue; | 600 | continue; |
| 596 | }, | 601 | }, |
| 597 | .c_mut_pointer => { | 602 | .c_mut_pointer => { |
| 598 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 603 | const pointee_type = ty.castTag(.c_mut_pointer).?.data; |
| 599 | try out_stream.writeAll("[*c]"); | 604 | try out_stream.writeAll("[*c]"); |
| 600 | ty = payload.pointee_type; | 605 | ty = pointee_type; |
| 601 | continue; | 606 | continue; |
| 602 | }, | 607 | }, |
| 603 | .const_slice => { | 608 | .const_slice => { |
| 604 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 609 | const pointee_type = ty.castTag(.const_slice).?.data; |
| 605 | try out_stream.writeAll("[]const "); | 610 | try out_stream.writeAll("[]const "); |
| 606 | ty = payload.pointee_type; | 611 | ty = pointee_type; |
| 607 | continue; | 612 | continue; |
| 608 | }, | 613 | }, |
| 609 | .mut_slice => { | 614 | .mut_slice => { |
| 610 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 615 | const pointee_type = ty.castTag(.mut_slice).?.data; |
| 611 | try out_stream.writeAll("[]"); | 616 | try out_stream.writeAll("[]"); |
| 612 | ty = payload.pointee_type; | 617 | ty = pointee_type; |
| 613 | continue; | 618 | continue; |
| 614 | }, | 619 | }, |
| 615 | .int_signed => { | 620 | .int_signed => { |
| 616 | const payload = @fieldParentPtr(Payload.IntSigned, "base", ty.ptr_otherwise); | 621 | const bits = ty.castTag(.int_signed).?.data; |
| 617 | return out_stream.print("i{}", .{payload.bits}); | 622 | return out_stream.print("i{d}", .{bits}); |
| 618 | }, | 623 | }, |
| 619 | .int_unsigned => { | 624 | .int_unsigned => { |
| 620 | const payload = @fieldParentPtr(Payload.IntUnsigned, "base", ty.ptr_otherwise); | 625 | const bits = ty.castTag(.int_unsigned).?.data; |
| 621 | return out_stream.print("u{}", .{payload.bits}); | 626 | return out_stream.print("u{d}", .{bits}); |
| 622 | }, | 627 | }, |
| 623 | .optional => { | 628 | .optional => { |
| 624 | const payload = @fieldParentPtr(Payload.Optional, "base", ty.ptr_otherwise); | 629 | const child_type = ty.castTag(.optional).?.data; |
| 625 | try out_stream.writeByte('?'); | 630 | try out_stream.writeByte('?'); |
| 626 | ty = payload.child_type; | 631 | ty = child_type; |
| 627 | continue; | 632 | continue; |
| 628 | }, | 633 | }, |
| 629 | .optional_single_const_pointer => { | 634 | .optional_single_const_pointer => { |
| 630 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 635 | const pointee_type = ty.castTag(.optional_single_const_pointer).?.data; |
| 631 | try out_stream.writeAll("?*const "); | 636 | try out_stream.writeAll("?*const "); |
| 632 | ty = payload.pointee_type; | 637 | ty = pointee_type; |
| 633 | continue; | 638 | continue; |
| 634 | }, | 639 | }, |
| 635 | .optional_single_mut_pointer => { | 640 | .optional_single_mut_pointer => { |
| 636 | const payload = @fieldParentPtr(Payload.PointerSimple, "base", ty.ptr_otherwise); | 641 | const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data; |
| 637 | try out_stream.writeAll("?*"); | 642 | try out_stream.writeAll("?*"); |
| 638 | ty = payload.pointee_type; | 643 | ty = pointee_type; |
| 639 | continue; | 644 | continue; |
| 640 | }, | 645 | }, |
| 641 | | 646 | |
| 642 | .pointer => { | 647 | .pointer => { |
| 643 | const payload = @fieldParentPtr(Payload.Pointer, "base", ty.ptr_otherwise); | 648 | const payload = ty.castTag(.pointer).?.data; |
| 644 | if (payload.sentinel) |some| switch (payload.size) { | 649 | if (payload.sentinel) |some| switch (payload.size) { |
| 645 | .One, .C => unreachable, | 650 | .One, .C => unreachable, |
| 646 | .Many => try out_stream.print("[*:{}]", .{some}), | 651 | .Many => try out_stream.print("[*:{}]", .{some}), |
| ... | @@ -652,10 +657,10 @@ pub const Type = extern union { | ... | @@ -652,10 +657,10 @@ pub const Type = extern union { |
| 652 | .Slice => try out_stream.writeAll("[]"), | 657 | .Slice => try out_stream.writeAll("[]"), |
| 653 | } | 658 | } |
| 654 | if (payload.@"align" != 0) { | 659 | if (payload.@"align" != 0) { |
| 655 | try out_stream.print("align({}", .{payload.@"align"}); | 660 | try out_stream.print("align({d}", .{payload.@"align"}); |
| 656 | | 661 | |
| 657 | if (payload.bit_offset != 0) { | 662 | if (payload.bit_offset != 0) { |
| 658 | try out_stream.print(":{}:{}", .{ payload.bit_offset, payload.host_size }); | 663 | try out_stream.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size }); |
| 659 | } | 664 | } |
| 660 | try out_stream.writeAll(") "); | 665 | try out_stream.writeAll(") "); |
| 661 | } | 666 | } |
| ... | @@ -667,19 +672,19 @@ pub const Type = extern union { | ... | @@ -667,19 +672,19 @@ pub const Type = extern union { |
| 667 | continue; | 672 | continue; |
| 668 | }, | 673 | }, |
| 669 | .error_union => { | 674 | .error_union => { |
| 670 | const payload = @fieldParentPtr(Payload.ErrorUnion, "base", ty.ptr_otherwise); | 675 | const payload = ty.castTag(.error_union).?.data; |
| 671 | try payload.error_set.format("", .{}, out_stream); | 676 | try payload.error_set.format("", .{}, out_stream); |
| 672 | try out_stream.writeAll("!"); | 677 | try out_stream.writeAll("!"); |
| 673 | ty = payload.payload; | 678 | ty = payload.payload; |
| 674 | continue; | 679 | continue; |
| 675 | }, | 680 | }, |
| 676 | .error_set => { | 681 | .error_set => { |
| 677 | const payload = @fieldParentPtr(Payload.ErrorSet, "base", ty.ptr_otherwise); | 682 | const decl = ty.castTag(.error_set).?.data; |
| 678 | return out_stream.writeAll(std.mem.spanZ(payload.decl.name)); | 683 | return out_stream.writeAll(std.mem.spanZ(decl.name)); |
| 679 | }, | 684 | }, |
| 680 | .error_set_single => { | 685 | .error_set_single => { |
| 681 | const payload = @fieldParentPtr(Payload.ErrorSetSingle, "base", ty.ptr_otherwise); | 686 | const name = ty.castTag(.error_set_single).?.data; |
| 682 | return out_stream.print("error{{{}}}", .{payload.name}); | 687 | return out_stream.print("error{{{s}}}", .{name}); |
| 683 | }, | 688 | }, |
| 684 | } | 689 | } |
| 685 | unreachable; | 690 | unreachable; |
| ... | @@ -784,11 +789,10 @@ pub const Type = extern union { | ... | @@ -784,11 +789,10 @@ pub const Type = extern union { |
| 784 | .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, | 789 | .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0, |
| 785 | .array_u8 => self.arrayLen() != 0, | 790 | .array_u8 => self.arrayLen() != 0, |
| 786 | .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(), | 791 | .array_sentinel, .single_const_pointer, .single_mut_pointer, .many_const_pointer, .many_mut_pointer, .c_const_pointer, .c_mut_pointer, .const_slice, .mut_slice, .pointer => self.elemType().hasCodeGenBits(), |
| 787 | .int_signed => self.cast(Payload.IntSigned).?.bits != 0, | 792 | .int_signed, .int_unsigned => self.cast(Payload.Bits).?.data != 0, |
| 788 | .int_unsigned => self.cast(Payload.IntUnsigned).?.bits != 0, | | |
| 789 | | 793 | |
| 790 | .error_union => { | 794 | .error_union => { |
| 791 | const payload = self.cast(Payload.ErrorUnion).?; | 795 | const payload = self.castTag(.error_union).?.data; |
| 792 | return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits(); | 796 | return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits(); |
| 793 | }, | 797 | }, |
| 794 | | 798 | |
| ... | @@ -855,7 +859,7 @@ pub const Type = extern union { | ... | @@ -855,7 +859,7 @@ pub const Type = extern union { |
| 855 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), | 859 | => return @divExact(target.cpu.arch.ptrBitWidth(), 8), |
| 856 | | 860 | |
| 857 | .pointer => { | 861 | .pointer => { |
| 858 | const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); | 862 | const payload = self.castTag(.pointer).?.data; |
| 859 | | 863 | |
| 860 | if (payload.@"align" != 0) return payload.@"align"; | 864 | if (payload.@"align" != 0) return payload.@"align"; |
| 861 | return @divExact(target.cpu.arch.ptrBitWidth(), 8); | 865 | return @divExact(target.cpu.arch.ptrBitWidth(), 8); |
| ... | @@ -885,18 +889,12 @@ pub const Type = extern union { | ... | @@ -885,18 +889,12 @@ pub const Type = extern union { |
| 885 | .array, .array_sentinel => return self.elemType().abiAlignment(target), | 889 | .array, .array_sentinel => return self.elemType().abiAlignment(target), |
| 886 | | 890 | |
| 887 | .int_signed, .int_unsigned => { | 891 | .int_signed, .int_unsigned => { |
| 888 | const bits: u16 = if (self.cast(Payload.IntSigned)) |pl| | 892 | const bits: u16 = self.cast(Payload.Bits).?.data; |
| 889 | pl.bits | | |
| 890 | else if (self.cast(Payload.IntUnsigned)) |pl| | | |
| 891 | pl.bits | | |
| 892 | else | | |
| 893 | unreachable; | | |
| 894 | | | |
| 895 | return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); | 893 | return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); |
| 896 | }, | 894 | }, |
| 897 | | 895 | |
| 898 | .optional => { | 896 | .optional => { |
| 899 | var buf: Payload.PointerSimple = undefined; | 897 | var buf: Payload.ElemType = undefined; |
| 900 | const child_type = self.optionalChild(&buf); | 898 | const child_type = self.optionalChild(&buf); |
| 901 | if (!child_type.hasCodeGenBits()) return 1; | 899 | if (!child_type.hasCodeGenBits()) return 1; |
| 902 | | 900 | |
| ... | @@ -907,7 +905,7 @@ pub const Type = extern union { | ... | @@ -907,7 +905,7 @@ pub const Type = extern union { |
| 907 | }, | 905 | }, |
| 908 | | 906 | |
| 909 | .error_union => { | 907 | .error_union => { |
| 910 | const payload = self.cast(Payload.ErrorUnion).?; | 908 | const payload = self.castTag(.error_union).?.data; |
| 911 | if (!payload.error_set.hasCodeGenBits()) { | 909 | if (!payload.error_set.hasCodeGenBits()) { |
| 912 | return payload.payload.abiAlignment(target); | 910 | return payload.payload.abiAlignment(target); |
| 913 | } else if (!payload.payload.hasCodeGenBits()) { | 911 | } else if (!payload.payload.hasCodeGenBits()) { |
| ... | @@ -955,16 +953,19 @@ pub const Type = extern union { | ... | @@ -955,16 +953,19 @@ pub const Type = extern union { |
| 955 | .bool, | 953 | .bool, |
| 956 | => return 1, | 954 | => return 1, |
| 957 | | 955 | |
| 958 | .array_u8 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len, | 956 | .array_u8 => self.castTag(.array_u8).?.data, |
| 959 | .array_u8_sentinel_0 => @fieldParentPtr(Payload.Array_u8_Sentinel0, "base", self.ptr_otherwise).len + 1, | 957 | .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data + 1, |
| 960 | .array => { | 958 | .array => { |
| 961 | const payload = @fieldParentPtr(Payload.Array, "base", self.ptr_otherwise); | 959 | const payload = self.castTag(.array).?.data; |
| 962 | const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); | 960 | const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); |
| 963 | return payload.len * elem_size; | 961 | return payload.len * elem_size; |
| 964 | }, | 962 | }, |
| 965 | .array_sentinel => { | 963 | .array_sentinel => { |
| 966 | const payload = @fieldParentPtr(Payload.ArraySentinel, "base", self.ptr_otherwise); | 964 | const payload = self.castTag(.array_sentinel).?.data; |
| 967 | const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target)); | 965 | const elem_size = std.math.max( |
| | 966 | payload.elem_type.abiAlignment(target), |
| | 967 | payload.elem_type.abiSize(target), |
| | 968 | ); |
| 968 | return (payload.len + 1) * elem_size; | 969 | return (payload.len + 1) * elem_size; |
| 969 | }, | 970 | }, |
| 970 | .i16, .u16 => return 2, | 971 | .i16, .u16 => return 2, |
| ... | @@ -1022,18 +1023,12 @@ pub const Type = extern union { | ... | @@ -1022,18 +1023,12 @@ pub const Type = extern union { |
| 1022 | => return 2, // TODO revisit this when we have the concept of the error tag type | 1023 | => return 2, // TODO revisit this when we have the concept of the error tag type |
| 1023 | | 1024 | |
| 1024 | .int_signed, .int_unsigned => { | 1025 | .int_signed, .int_unsigned => { |
| 1025 | const bits: u16 = if (self.cast(Payload.IntSigned)) |pl| | 1026 | const bits: u16 = self.cast(Payload.Bits).?.data; |
| 1026 | pl.bits | | |
| 1027 | else if (self.cast(Payload.IntUnsigned)) |pl| | | |
| 1028 | pl.bits | | |
| 1029 | else | | |
| 1030 | unreachable; | | |
| 1031 | | | |
| 1032 | return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); | 1027 | return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8); |
| 1033 | }, | 1028 | }, |
| 1034 | | 1029 | |
| 1035 | .optional => { | 1030 | .optional => { |
| 1036 | var buf: Payload.PointerSimple = undefined; | 1031 | var buf: Payload.ElemType = undefined; |
| 1037 | const child_type = self.optionalChild(&buf); | 1032 | const child_type = self.optionalChild(&buf); |
| 1038 | if (!child_type.hasCodeGenBits()) return 1; | 1033 | if (!child_type.hasCodeGenBits()) return 1; |
| 1039 | | 1034 | |
| ... | @@ -1048,7 +1043,7 @@ pub const Type = extern union { | ... | @@ -1048,7 +1043,7 @@ pub const Type = extern union { |
| 1048 | }, | 1043 | }, |
| 1049 | | 1044 | |
| 1050 | .error_union => { | 1045 | .error_union => { |
| 1051 | const payload = self.cast(Payload.ErrorUnion).?; | 1046 | const payload = self.castTag(.error_union).?.data; |
| 1052 | if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) { | 1047 | if (!payload.error_set.hasCodeGenBits() and !payload.payload.hasCodeGenBits()) { |
| 1053 | return 0; | 1048 | return 0; |
| 1054 | } else if (!payload.error_set.hasCodeGenBits()) { | 1049 | } else if (!payload.error_set.hasCodeGenBits()) { |
| ... | @@ -1132,7 +1127,7 @@ pub const Type = extern union { | ... | @@ -1132,7 +1127,7 @@ pub const Type = extern union { |
| 1132 | .single_const_pointer_to_comptime_int, | 1127 | .single_const_pointer_to_comptime_int, |
| 1133 | => true, | 1128 | => true, |
| 1134 | | 1129 | |
| 1135 | .pointer => self.cast(Payload.Pointer).?.size == .One, | 1130 | .pointer => self.castTag(.pointer).?.data.size == .One, |
| 1136 | }; | 1131 | }; |
| 1137 | } | 1132 | } |
| 1138 | | 1133 | |
| ... | @@ -1214,7 +1209,7 @@ pub const Type = extern union { | ... | @@ -1214,7 +1209,7 @@ pub const Type = extern union { |
| 1214 | .single_const_pointer_to_comptime_int, | 1209 | .single_const_pointer_to_comptime_int, |
| 1215 | => .One, | 1210 | => .One, |
| 1216 | | 1211 | |
| 1217 | .pointer => self.cast(Payload.Pointer).?.size, | 1212 | .pointer => self.castTag(.pointer).?.data.size, |
| 1218 | }; | 1213 | }; |
| 1219 | } | 1214 | } |
| 1220 | | 1215 | |
| ... | @@ -1289,7 +1284,7 @@ pub const Type = extern union { | ... | @@ -1289,7 +1284,7 @@ pub const Type = extern union { |
| 1289 | .const_slice_u8, | 1284 | .const_slice_u8, |
| 1290 | => true, | 1285 | => true, |
| 1291 | | 1286 | |
| 1292 | .pointer => self.cast(Payload.Pointer).?.size == .Slice, | 1287 | .pointer => self.castTag(.pointer).?.data.size == .Slice, |
| 1293 | }; | 1288 | }; |
| 1294 | } | 1289 | } |
| 1295 | | 1290 | |
| ... | @@ -1364,7 +1359,7 @@ pub const Type = extern union { | ... | @@ -1364,7 +1359,7 @@ pub const Type = extern union { |
| 1364 | .const_slice, | 1359 | .const_slice, |
| 1365 | => true, | 1360 | => true, |
| 1366 | | 1361 | |
| 1367 | .pointer => !self.cast(Payload.Pointer).?.mutable, | 1362 | .pointer => !self.castTag(.pointer).?.data.mutable, |
| 1368 | }; | 1363 | }; |
| 1369 | } | 1364 | } |
| 1370 | | 1365 | |
| ... | @@ -1438,7 +1433,7 @@ pub const Type = extern union { | ... | @@ -1438,7 +1433,7 @@ pub const Type = extern union { |
| 1438 | => false, | 1433 | => false, |
| 1439 | | 1434 | |
| 1440 | .pointer => { | 1435 | .pointer => { |
| 1441 | const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); | 1436 | const payload = self.castTag(.pointer).?.data; |
| 1442 | return payload.@"volatile"; | 1437 | return payload.@"volatile"; |
| 1443 | }, | 1438 | }, |
| 1444 | }; | 1439 | }; |
| ... | @@ -1514,7 +1509,7 @@ pub const Type = extern union { | ... | @@ -1514,7 +1509,7 @@ pub const Type = extern union { |
| 1514 | => false, | 1509 | => false, |
| 1515 | | 1510 | |
| 1516 | .pointer => { | 1511 | .pointer => { |
| 1517 | const payload = @fieldParentPtr(Payload.Pointer, "base", self.ptr_otherwise); | 1512 | const payload = self.castTag(.pointer).?.data; |
| 1518 | return payload.@"allowzero"; | 1513 | return payload.@"allowzero"; |
| 1519 | }, | 1514 | }, |
| 1520 | }; | 1515 | }; |
| ... | @@ -1525,7 +1520,7 @@ pub const Type = extern union { | ... | @@ -1525,7 +1520,7 @@ pub const Type = extern union { |
| 1525 | switch (self.tag()) { | 1520 | switch (self.tag()) { |
| 1526 | .optional_single_const_pointer, .optional_single_mut_pointer => return true, | 1521 | .optional_single_const_pointer, .optional_single_mut_pointer => return true, |
| 1527 | .optional => { | 1522 | .optional => { |
| 1528 | var buf: Payload.PointerSimple = undefined; | 1523 | var buf: Payload.ElemType = undefined; |
| 1529 | const child_type = self.optionalChild(&buf); | 1524 | const child_type = self.optionalChild(&buf); |
| 1530 | // optionals of zero sized pointers behave like bools | 1525 | // optionals of zero sized pointers behave like bools |
| 1531 | if (!child_type.hasCodeGenBits()) return false; | 1526 | if (!child_type.hasCodeGenBits()) return false; |
| ... | @@ -1563,7 +1558,7 @@ pub const Type = extern union { | ... | @@ -1563,7 +1558,7 @@ pub const Type = extern union { |
| 1563 | => return false, | 1558 | => return false, |
| 1564 | | 1559 | |
| 1565 | .Optional => { | 1560 | .Optional => { |
| 1566 | var buf: Payload.PointerSimple = undefined; | 1561 | var buf: Payload.ElemType = undefined; |
| 1567 | return ty.optionalChild(&buf).isValidVarType(is_extern); | 1562 | return ty.optionalChild(&buf).isValidVarType(is_extern); |
| 1568 | }, | 1563 | }, |
| 1569 | .Pointer, .Array => ty = ty.elemType(), | 1564 | .Pointer, .Array => ty = ty.elemType(), |
| ... | @@ -1631,8 +1626,8 @@ pub const Type = extern union { | ... | @@ -1631,8 +1626,8 @@ pub const Type = extern union { |
| 1631 | .empty_struct, | 1626 | .empty_struct, |
| 1632 | => unreachable, | 1627 | => unreachable, |
| 1633 | | 1628 | |
| 1634 | .array => self.cast(Payload.Array).?.elem_type, | 1629 | .array => self.castTag(.array).?.data.elem_type, |
| 1635 | .array_sentinel => self.cast(Payload.ArraySentinel).?.elem_type, | 1630 | .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, |
| 1636 | .single_const_pointer, | 1631 | .single_const_pointer, |
| 1637 | .single_mut_pointer, | 1632 | .single_mut_pointer, |
| 1638 | .many_const_pointer, | 1633 | .many_const_pointer, |
| ... | @@ -1641,28 +1636,29 @@ pub const Type = extern union { | ... | @@ -1641,28 +1636,29 @@ pub const Type = extern union { |
| 1641 | .c_mut_pointer, | 1636 | .c_mut_pointer, |
| 1642 | .const_slice, | 1637 | .const_slice, |
| 1643 | .mut_slice, | 1638 | .mut_slice, |
| 1644 | => self.castPointer().?.pointee_type, | 1639 | => self.castPointer().?.data, |
| 1645 | .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8), | 1640 | .array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8), |
| 1646 | .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int), | 1641 | .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int), |
| 1647 | .pointer => self.cast(Payload.Pointer).?.pointee_type, | 1642 | .pointer => self.castTag(.pointer).?.data.pointee_type, |
| 1648 | }; | 1643 | }; |
| 1649 | } | 1644 | } |
| 1650 | | 1645 | |
| 1651 | /// Asserts that the type is an optional. | 1646 | /// Asserts that the type is an optional. |
| 1652 | pub fn optionalChild(self: Type, buf: *Payload.PointerSimple) Type { | 1647 | /// Resulting `Type` will have inner memory referencing `buf`. |
| | 1648 | pub fn optionalChild(self: Type, buf: *Payload.ElemType) Type { |
| 1653 | return switch (self.tag()) { | 1649 | return switch (self.tag()) { |
| 1654 | .optional => self.cast(Payload.Optional).?.child_type, | 1650 | .optional => self.castTag(.optional).?.data, |
| 1655 | .optional_single_mut_pointer => { | 1651 | .optional_single_mut_pointer => { |
| 1656 | buf.* = .{ | 1652 | buf.* = .{ |
| 1657 | .base = .{ .tag = .single_mut_pointer }, | 1653 | .base = .{ .tag = .single_mut_pointer }, |
| 1658 | .pointee_type = self.castPointer().?.pointee_type, | 1654 | .data = self.castPointer().?.data, |
| 1659 | }; | 1655 | }; |
| 1660 | return Type.initPayload(&buf.base); | 1656 | return Type.initPayload(&buf.base); |
| 1661 | }, | 1657 | }, |
| 1662 | .optional_single_const_pointer => { | 1658 | .optional_single_const_pointer => { |
| 1663 | buf.* = .{ | 1659 | buf.* = .{ |
| 1664 | .base = .{ .tag = .single_const_pointer }, | 1660 | .base = .{ .tag = .single_const_pointer }, |
| 1665 | .pointee_type = self.castPointer().?.pointee_type, | 1661 | .data = self.castPointer().?.data, |
| 1666 | }; | 1662 | }; |
| 1667 | return Type.initPayload(&buf.base); | 1663 | return Type.initPayload(&buf.base); |
| 1668 | }, | 1664 | }, |
| ... | @@ -1673,23 +1669,16 @@ pub const Type = extern union { | ... | @@ -1673,23 +1669,16 @@ pub const Type = extern union { |
| 1673 | /// Asserts that the type is an optional. | 1669 | /// Asserts that the type is an optional. |
| 1674 | /// Same as `optionalChild` but allocates the buffer if needed. | 1670 | /// Same as `optionalChild` but allocates the buffer if needed. |
| 1675 | pub fn optionalChildAlloc(self: Type, allocator: *Allocator) !Type { | 1671 | pub fn optionalChildAlloc(self: Type, allocator: *Allocator) !Type { |
| 1676 | return switch (self.tag()) { | 1672 | switch (self.tag()) { |
| 1677 | .optional => self.cast(Payload.Optional).?.child_type, | 1673 | .optional => return self.castTag(.optional).?.data, |
| 1678 | .optional_single_mut_pointer, .optional_single_const_pointer => { | 1674 | .optional_single_mut_pointer => { |
| 1679 | const payload = try allocator.create(Payload.PointerSimple); | 1675 | return Tag.single_mut_pointer.create(allocator, self.castPointer().?.data); |
| 1680 | payload.* = .{ | 1676 | }, |
| 1681 | .base = .{ | 1677 | .optional_single_const_pointer => { |
| 1682 | .tag = if (self.tag() == .optional_single_const_pointer) | 1678 | return Tag.single_const_pointer.create(allocator, self.castPointer().?.data); |
| 1683 | .single_const_pointer | | |
| 1684 | else | | |
| 1685 | .single_mut_pointer, | | |
| 1686 | }, | | |
| 1687 | .pointee_type = self.castPointer().?.pointee_type, | | |
| 1688 | }; | | |
| 1689 | return Type.initPayload(&payload.base); | | |
| 1690 | }, | 1679 | }, |
| 1691 | else => unreachable, | 1680 | else => unreachable, |
| 1692 | }; | 1681 | } |
| 1693 | } | 1682 | } |
| 1694 | | 1683 | |
| 1695 | /// Asserts the type is an array or vector. | 1684 | /// Asserts the type is an array or vector. |
| ... | @@ -1759,10 +1748,10 @@ pub const Type = extern union { | ... | @@ -1759,10 +1748,10 @@ pub const Type = extern union { |
| 1759 | .empty_struct, | 1748 | .empty_struct, |
| 1760 | => unreachable, | 1749 | => unreachable, |
| 1761 | | 1750 | |
| 1762 | .array => self.cast(Payload.Array).?.len, | 1751 | .array => self.castTag(.array).?.data.len, |
| 1763 | .array_sentinel => self.cast(Payload.ArraySentinel).?.len, | 1752 | .array_sentinel => self.castTag(.array_sentinel).?.data.len, |
| 1764 | .array_u8 => self.cast(Payload.Array_u8).?.len, | 1753 | .array_u8 => self.castTag(.array_u8).?.data, |
| 1765 | .array_u8_sentinel_0 => self.cast(Payload.Array_u8_Sentinel0).?.len, | 1754 | .array_u8_sentinel_0 => self.castTag(.array_u8_sentinel_0).?.data, |
| 1766 | }; | 1755 | }; |
| 1767 | } | 1756 | } |
| 1768 | | 1757 | |
| ... | @@ -1836,8 +1825,8 @@ pub const Type = extern union { | ... | @@ -1836,8 +1825,8 @@ pub const Type = extern union { |
| 1836 | .array_u8, | 1825 | .array_u8, |
| 1837 | => return null, | 1826 | => return null, |
| 1838 | | 1827 | |
| 1839 | .pointer => return self.cast(Payload.Pointer).?.sentinel, | 1828 | .pointer => return self.castTag(.pointer).?.data.sentinel, |
| 1840 | .array_sentinel => return self.cast(Payload.ArraySentinel).?.sentinel, | 1829 | .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel, |
| 1841 | .array_u8_sentinel_0 => return Value.initTag(.zero), | 1830 | .array_u8_sentinel_0 => return Value.initTag(.zero), |
| 1842 | }; | 1831 | }; |
| 1843 | } | 1832 | } |
| ... | @@ -2048,8 +2037,14 @@ pub const Type = extern union { | ... | @@ -2048,8 +2037,14 @@ pub const Type = extern union { |
| 2048 | .empty_struct, | 2037 | .empty_struct, |
| 2049 | => unreachable, | 2038 | => unreachable, |
| 2050 | | 2039 | |
| 2051 | .int_unsigned => .{ .signedness = .unsigned, .bits = self.cast(Payload.IntUnsigned).?.bits }, | 2040 | .int_unsigned => .{ |
| 2052 | .int_signed => .{ .signedness = .signed, .bits = self.cast(Payload.IntSigned).?.bits }, | 2041 | .signedness = .unsigned, |
| | 2042 | .bits = self.castTag(.int_unsigned).?.data, |
| | 2043 | }, |
| | 2044 | .int_signed => .{ |
| | 2045 | .signedness = .signed, |
| | 2046 | .bits = self.castTag(.int_signed).?.data, |
| | 2047 | }, |
| 2053 | .u8 => .{ .signedness = .unsigned, .bits = 8 }, | 2048 | .u8 => .{ .signedness = .unsigned, .bits = 8 }, |
| 2054 | .i8 => .{ .signedness = .signed, .bits = 8 }, | 2049 | .i8 => .{ .signedness = .signed, .bits = 8 }, |
| 2055 | .u16 => .{ .signedness = .unsigned, .bits = 16 }, | 2050 | .u16 => .{ .signedness = .unsigned, .bits = 16 }, |
| ... | @@ -2178,7 +2173,7 @@ pub const Type = extern union { | ... | @@ -2178,7 +2173,7 @@ pub const Type = extern union { |
| 2178 | .fn_void_no_args => 0, | 2173 | .fn_void_no_args => 0, |
| 2179 | .fn_naked_noreturn_no_args => 0, | 2174 | .fn_naked_noreturn_no_args => 0, |
| 2180 | .fn_ccc_void_no_args => 0, | 2175 | .fn_ccc_void_no_args => 0, |
| 2181 | .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).param_types.len, | 2176 | .function => self.castTag(.function).?.data.param_types.len, |
| 2182 | | 2177 | |
| 2183 | .f16, | 2178 | .f16, |
| 2184 | .f32, | 2179 | .f32, |
| ... | @@ -2254,7 +2249,7 @@ pub const Type = extern union { | ... | @@ -2254,7 +2249,7 @@ pub const Type = extern union { |
| 2254 | .fn_naked_noreturn_no_args => return, | 2249 | .fn_naked_noreturn_no_args => return, |
| 2255 | .fn_ccc_void_no_args => return, | 2250 | .fn_ccc_void_no_args => return, |
| 2256 | .function => { | 2251 | .function => { |
| 2257 | const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise); | 2252 | const payload = self.castTag(.function).?.data; |
| 2258 | std.mem.copy(Type, types, payload.param_types); | 2253 | std.mem.copy(Type, types, payload.param_types); |
| 2259 | }, | 2254 | }, |
| 2260 | | 2255 | |
| ... | @@ -2327,7 +2322,7 @@ pub const Type = extern union { | ... | @@ -2327,7 +2322,7 @@ pub const Type = extern union { |
| 2327 | pub fn fnParamType(self: Type, index: usize) Type { | 2322 | pub fn fnParamType(self: Type, index: usize) Type { |
| 2328 | switch (self.tag()) { | 2323 | switch (self.tag()) { |
| 2329 | .function => { | 2324 | .function => { |
| 2330 | const payload = @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise); | 2325 | const payload = self.castTag(.function).?.data; |
| 2331 | return payload.param_types[index]; | 2326 | return payload.param_types[index]; |
| 2332 | }, | 2327 | }, |
| 2333 | | 2328 | |
| ... | @@ -2410,7 +2405,7 @@ pub const Type = extern union { | ... | @@ -2410,7 +2405,7 @@ pub const Type = extern union { |
| 2410 | .fn_ccc_void_no_args, | 2405 | .fn_ccc_void_no_args, |
| 2411 | => Type.initTag(.void), | 2406 | => Type.initTag(.void), |
| 2412 | | 2407 | |
| 2413 | .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).return_type, | 2408 | .function => self.castTag(.function).?.data.return_type, |
| 2414 | | 2409 | |
| 2415 | .f16, | 2410 | .f16, |
| 2416 | .f32, | 2411 | .f32, |
| ... | @@ -2484,7 +2479,7 @@ pub const Type = extern union { | ... | @@ -2484,7 +2479,7 @@ pub const Type = extern union { |
| 2484 | .fn_void_no_args => .Unspecified, | 2479 | .fn_void_no_args => .Unspecified, |
| 2485 | .fn_naked_noreturn_no_args => .Naked, | 2480 | .fn_naked_noreturn_no_args => .Naked, |
| 2486 | .fn_ccc_void_no_args => .C, | 2481 | .fn_ccc_void_no_args => .C, |
| 2487 | .function => @fieldParentPtr(Payload.Function, "base", self.ptr_otherwise).cc, | 2482 | .function => self.castTag(.function).?.data.cc, |
| 2488 | | 2483 | |
| 2489 | .f16, | 2484 | .f16, |
| 2490 | .f32, | 2485 | .f32, |
| ... | @@ -2760,15 +2755,8 @@ pub const Type = extern union { | ... | @@ -2760,15 +2755,8 @@ pub const Type = extern union { |
| 2760 | .@"null" => return Value.initTag(.null_value), | 2755 | .@"null" => return Value.initTag(.null_value), |
| 2761 | .@"undefined" => return Value.initTag(.undef), | 2756 | .@"undefined" => return Value.initTag(.undef), |
| 2762 | | 2757 | |
| 2763 | .int_unsigned => { | 2758 | .int_unsigned, .int_signed => { |
| 2764 | if (ty.cast(Payload.IntUnsigned).?.bits == 0) { | 2759 | if (ty.cast(Payload.Bits).?.data == 0) { |
| 2765 | return Value.initTag(.zero); | | |
| 2766 | } else { | | |
| 2767 | return null; | | |
| 2768 | } | | |
| 2769 | }, | | |
| 2770 | .int_signed => { | | |
| 2771 | if (ty.cast(Payload.IntSigned).?.bits == 0) { | | |
| 2772 | return Value.initTag(.zero); | 2760 | return Value.initTag(.zero); |
| 2773 | } else { | 2761 | } else { |
| 2774 | return null; | 2762 | return null; |
| ... | @@ -2787,12 +2775,11 @@ pub const Type = extern union { | ... | @@ -2787,12 +2775,11 @@ pub const Type = extern union { |
| 2787 | .single_const_pointer, | 2775 | .single_const_pointer, |
| 2788 | .single_mut_pointer, | 2776 | .single_mut_pointer, |
| 2789 | => { | 2777 | => { |
| 2790 | const ptr = ty.castPointer().?; | 2778 | ty = ty.castPointer().?.data; |
| 2791 | ty = ptr.pointee_type; | | |
| 2792 | continue; | 2779 | continue; |
| 2793 | }, | 2780 | }, |
| 2794 | .pointer => { | 2781 | .pointer => { |
| 2795 | ty = ty.cast(Payload.Pointer).?.pointee_type; | 2782 | ty = ty.castTag(.pointer).?.data.pointee_type; |
| 2796 | continue; | 2783 | continue; |
| 2797 | }, | 2784 | }, |
| 2798 | }; | 2785 | }; |
| ... | @@ -2869,7 +2856,7 @@ pub const Type = extern union { | ... | @@ -2869,7 +2856,7 @@ pub const Type = extern union { |
| 2869 | .c_mut_pointer, | 2856 | .c_mut_pointer, |
| 2870 | => return true, | 2857 | => return true, |
| 2871 | | 2858 | |
| 2872 | .pointer => self.cast(Payload.Pointer).?.size == .C, | 2859 | .pointer => self.castTag(.pointer).?.data.size == .C, |
| 2873 | }; | 2860 | }; |
| 2874 | } | 2861 | } |
| 2875 | | 2862 | |
| ... | @@ -2950,7 +2937,7 @@ pub const Type = extern union { | ... | @@ -2950,7 +2937,7 @@ pub const Type = extern union { |
| 2950 | .pointer, | 2937 | .pointer, |
| 2951 | => unreachable, | 2938 | => unreachable, |
| 2952 | | 2939 | |
| 2953 | .empty_struct => self.cast(Type.Payload.EmptyStruct).?.scope, | 2940 | .empty_struct => self.castTag(.empty_struct).?.data, |
| 2954 | }; | 2941 | }; |
| 2955 | } | 2942 | } |
| 2956 | | 2943 | |
| ... | @@ -3105,117 +3092,195 @@ pub const Type = extern union { | ... | @@ -3105,117 +3092,195 @@ pub const Type = extern union { |
| 3105 | | 3092 | |
| 3106 | pub const last_no_payload_tag = Tag.const_slice_u8; | 3093 | pub const last_no_payload_tag = Tag.const_slice_u8; |
| 3107 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; | 3094 | pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1; |
| 3108 | }; | | |
| 3109 | | 3095 | |
| 3110 | pub const Payload = struct { | 3096 | pub fn Type(comptime t: Tag) type { |
| 3111 | tag: Tag, | 3097 | return switch (t) { |
| | 3098 | .u8, |
| | 3099 | .i8, |
| | 3100 | .u16, |
| | 3101 | .i16, |
| | 3102 | .u32, |
| | 3103 | .i32, |
| | 3104 | .u64, |
| | 3105 | .i64, |
| | 3106 | .usize, |
| | 3107 | .isize, |
| | 3108 | .c_short, |
| | 3109 | .c_ushort, |
| | 3110 | .c_int, |
| | 3111 | .c_uint, |
| | 3112 | .c_long, |
| | 3113 | .c_ulong, |
| | 3114 | .c_longlong, |
| | 3115 | .c_ulonglong, |
| | 3116 | .c_longdouble, |
| | 3117 | .f16, |
| | 3118 | .f32, |
| | 3119 | .f64, |
| | 3120 | .f128, |
| | 3121 | .c_void, |
| | 3122 | .bool, |
| | 3123 | .void, |
| | 3124 | .type, |
| | 3125 | .anyerror, |
| | 3126 | .comptime_int, |
| | 3127 | .comptime_float, |
| | 3128 | .noreturn, |
| | 3129 | .enum_literal, |
| | 3130 | .@"null", |
| | 3131 | .@"undefined", |
| | 3132 | .fn_noreturn_no_args, |
| | 3133 | .fn_void_no_args, |
| | 3134 | .fn_naked_noreturn_no_args, |
| | 3135 | .fn_ccc_void_no_args, |
| | 3136 | .single_const_pointer_to_comptime_int, |
| | 3137 | .anyerror_void_error_union, |
| | 3138 | .@"anyframe", |
| | 3139 | .const_slice_u8, |
| | 3140 | => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), |
| | 3141 | |
| | 3142 | .array_u8, |
| | 3143 | .array_u8_sentinel_0, |
| | 3144 | => Payload.Len, |
| | 3145 | |
| | 3146 | .single_const_pointer, |
| | 3147 | .single_mut_pointer, |
| | 3148 | .many_const_pointer, |
| | 3149 | .many_mut_pointer, |
| | 3150 | .c_const_pointer, |
| | 3151 | .c_mut_pointer, |
| | 3152 | .const_slice, |
| | 3153 | .mut_slice, |
| | 3154 | .optional, |
| | 3155 | .optional_single_mut_pointer, |
| | 3156 | .optional_single_const_pointer, |
| | 3157 | .anyframe_T, |
| | 3158 | => Payload.ElemType, |
| | 3159 | |
| | 3160 | .int_signed, |
| | 3161 | .int_unsigned, |
| | 3162 | => Payload.Bits, |
| | 3163 | |
| | 3164 | .array => Payload.Array, |
| | 3165 | .array_sentinel => Payload.ArraySentinel, |
| | 3166 | .pointer => Payload.Pointer, |
| | 3167 | .function => Payload.Function, |
| | 3168 | .error_union => Payload.ErrorUnion, |
| | 3169 | .error_set => Payload.Decl, |
| | 3170 | .error_set_single => Payload.Name, |
| | 3171 | .empty_struct => Payload.ContainerScope, |
| | 3172 | }; |
| | 3173 | } |
| 3112 | | 3174 | |
| 3113 | pub const Array_u8_Sentinel0 = struct { | 3175 | pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!Type { |
| 3114 | base: Payload = Payload{ .tag = .array_u8_sentinel_0 }, | 3176 | const ptr = try ally.create(t.Type()); |
| | 3177 | ptr.* = .{ |
| | 3178 | .base = .{ .tag = t }, |
| | 3179 | .data = data, |
| | 3180 | }; |
| | 3181 | return Type{ .ptr_otherwise = &ptr.base }; |
| | 3182 | } |
| 3115 | | 3183 | |
| 3116 | len: u64, | 3184 | pub fn Data(comptime t: Tag) type { |
| 3117 | }; | 3185 | return std.meta.fieldInfo(t.Type(), "data").field_type; |
| | 3186 | } |
| | 3187 | }; |
| 3118 | | 3188 | |
| 3119 | pub const Array_u8 = struct { | 3189 | /// The sub-types are named after what fields they contain. |
| 3120 | base: Payload = Payload{ .tag = .array_u8 }, | 3190 | pub const Payload = struct { |
| | 3191 | tag: Tag, |
| 3121 | | 3192 | |
| 3122 | len: u64, | 3193 | pub const Len = struct { |
| | 3194 | base: Payload, |
| | 3195 | data: u64, |
| 3123 | }; | 3196 | }; |
| 3124 | | 3197 | |
| 3125 | pub const Array = struct { | 3198 | pub const Array = struct { |
| 3126 | base: Payload = Payload{ .tag = .array }, | 3199 | pub const base_tag = Tag.array; |
| 3127 | | 3200 | |
| 3128 | len: u64, | 3201 | base: Payload = Payload{ .tag = base_tag }, |
| 3129 | elem_type: Type, | 3202 | data: struct { |
| | 3203 | len: u64, |
| | 3204 | elem_type: Type, |
| | 3205 | }, |
| 3130 | }; | 3206 | }; |
| 3131 | | 3207 | |
| 3132 | pub const ArraySentinel = struct { | 3208 | pub const ArraySentinel = struct { |
| 3133 | base: Payload = Payload{ .tag = .array_sentinel }, | 3209 | pub const base_tag = Tag.array_sentinel; |
| 3134 | | 3210 | |
| 3135 | len: u64, | 3211 | base: Payload = Payload{ .tag = base_tag }, |
| 3136 | sentinel: Value, | 3212 | data: struct { |
| 3137 | elem_type: Type, | 3213 | len: u64, |
| | 3214 | sentinel: Value, |
| | 3215 | elem_type: Type, |
| | 3216 | }, |
| 3138 | }; | 3217 | }; |
| 3139 | | 3218 | |
| 3140 | pub const PointerSimple = struct { | 3219 | pub const ElemType = struct { |
| 3141 | base: Payload, | 3220 | base: Payload, |
| 3142 | | 3221 | data: Type, |
| 3143 | pointee_type: Type, | | |
| 3144 | }; | 3222 | }; |
| 3145 | | 3223 | |
| 3146 | pub const IntSigned = struct { | 3224 | pub const Bits = struct { |
| 3147 | base: Payload = Payload{ .tag = .int_signed }, | 3225 | base: Payload, |
| 3148 | | 3226 | data: u16, |
| 3149 | bits: u16, | | |
| 3150 | }; | | |
| 3151 | | | |
| 3152 | pub const IntUnsigned = struct { | | |
| 3153 | base: Payload = Payload{ .tag = .int_unsigned }, | | |
| 3154 | | | |
| 3155 | bits: u16, | | |
| 3156 | }; | 3227 | }; |
| 3157 | | 3228 | |
| 3158 | pub const Function = struct { | 3229 | pub const Function = struct { |
| 3159 | base: Payload = Payload{ .tag = .function }, | 3230 | pub const base_tag = Tag.function; |
| 3160 | | | |
| 3161 | param_types: []Type, | | |
| 3162 | return_type: Type, | | |
| 3163 | cc: std.builtin.CallingConvention, | | |
| 3164 | }; | | |
| 3165 | | | |
| 3166 | pub const Optional = struct { | | |
| 3167 | base: Payload = Payload{ .tag = .optional }, | | |
| 3168 | | 3231 | |
| 3169 | child_type: Type, | 3232 | base: Payload = Payload{ .tag = base_tag }, |
| | 3233 | data: struct { |
| | 3234 | param_types: []Type, |
| | 3235 | return_type: Type, |
| | 3236 | cc: std.builtin.CallingConvention, |
| | 3237 | }, |
| 3170 | }; | 3238 | }; |
| 3171 | | 3239 | |
| 3172 | pub const Pointer = struct { | 3240 | pub const Pointer = struct { |
| 3173 | base: Payload = .{ .tag = .pointer }, | 3241 | pub const base_tag = Tag.pointer; |
| 3174 | | 3242 | |
| 3175 | pointee_type: Type, | 3243 | base: Payload = Payload{ .tag = base_tag }, |
| 3176 | sentinel: ?Value, | 3244 | data: struct { |
| 3177 | /// If zero use pointee_type.AbiAlign() | 3245 | pointee_type: Type, |
| 3178 | @"align": u32, | 3246 | sentinel: ?Value, |
| 3179 | bit_offset: u16, | 3247 | /// If zero use pointee_type.AbiAlign() |
| 3180 | host_size: u16, | 3248 | @"align": u32, |
| 3181 | @"allowzero": bool, | 3249 | bit_offset: u16, |
| 3182 | mutable: bool, | 3250 | host_size: u16, |
| 3183 | @"volatile": bool, | 3251 | @"allowzero": bool, |
| 3184 | size: std.builtin.TypeInfo.Pointer.Size, | 3252 | mutable: bool, |
| | 3253 | @"volatile": bool, |
| | 3254 | size: std.builtin.TypeInfo.Pointer.Size, |
| | 3255 | }, |
| 3185 | }; | 3256 | }; |
| 3186 | | 3257 | |
| 3187 | pub const ErrorUnion = struct { | 3258 | pub const ErrorUnion = struct { |
| 3188 | base: Payload = .{ .tag = .error_union }, | 3259 | pub const base_tag = Tag.error_union; |
| 3189 | | 3260 | |
| 3190 | error_set: Type, | 3261 | base: Payload = Payload{ .tag = base_tag }, |
| 3191 | payload: Type, | 3262 | data: struct { |
| 3192 | }; | 3263 | error_set: Type, |
| 3193 | | 3264 | payload: Type, |
| 3194 | pub const AnyFrame = struct { | 3265 | }, |
| 3195 | base: Payload = .{ .tag = .anyframe_T }, | | |
| 3196 | | | |
| 3197 | return_type: Type, | | |
| 3198 | }; | 3266 | }; |
| 3199 | | 3267 | |
| 3200 | pub const ErrorSet = struct { | 3268 | pub const Decl = struct { |
| 3201 | base: Payload = .{ .tag = .error_set }, | 3269 | base: Payload, |
| 3202 | | 3270 | data: *Module.Decl, |
| 3203 | decl: *Module.Decl, | | |
| 3204 | }; | 3271 | }; |
| 3205 | | 3272 | |
| 3206 | pub const ErrorSetSingle = struct { | 3273 | pub const Name = struct { |
| 3207 | base: Payload = .{ .tag = .error_set_single }, | 3274 | base: Payload, |
| 3208 | | | |
| 3209 | /// memory is owned by `Module` | 3275 | /// memory is owned by `Module` |
| 3210 | name: []const u8, | 3276 | data: []const u8, |
| 3211 | }; | 3277 | }; |
| 3212 | | 3278 | |
| 3213 | /// Mostly used for namespace like structs with zero fields. | 3279 | /// Mostly used for namespace like structs with zero fields. |
| 3214 | /// Most commonly used for files. | 3280 | /// Most commonly used for files. |
| 3215 | pub const EmptyStruct = struct { | 3281 | pub const ContainerScope = struct { |
| 3216 | base: Payload = .{ .tag = .empty_struct }, | 3282 | base: Payload, |
| 3217 | | 3283 | data: *Module.Scope.Container, |
| 3218 | scope: *Module.Scope.Container, | | |
| 3219 | }; | 3284 | }; |
| 3220 | }; | 3285 | }; |
| 3221 | }; | 3286 | }; |