stage2: add optional types
This commit is contained in:
@@ -70,6 +70,11 @@ pub const Type = extern union {
|
||||
.single_mut_pointer => return .Pointer,
|
||||
.single_const_pointer_to_comptime_int => return .Pointer,
|
||||
.const_slice_u8 => return .Pointer,
|
||||
|
||||
.optional,
|
||||
.optional_single_const_pointer,
|
||||
.optional_single_mut_pointer,
|
||||
=> return .Optional,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,9 +184,13 @@ pub const Type = extern union {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
.Optional => {
|
||||
if (a.tag() != b.tag())
|
||||
return false;
|
||||
return a.elemType().eql(b.elemType());
|
||||
},
|
||||
.Float,
|
||||
.Struct,
|
||||
.Optional,
|
||||
.ErrorUnion,
|
||||
.ErrorSet,
|
||||
.Enum,
|
||||
@@ -241,9 +250,11 @@ pub const Type = extern union {
|
||||
std.hash.autoHash(&hasher, self.fnParamType(i).hash());
|
||||
}
|
||||
},
|
||||
.Optional => {
|
||||
std.hash.autoHash(&hasher, self.elemType().hash());
|
||||
},
|
||||
.Float,
|
||||
.Struct,
|
||||
.Optional,
|
||||
.ErrorUnion,
|
||||
.ErrorSet,
|
||||
.Enum,
|
||||
@@ -317,24 +328,8 @@ pub const Type = extern union {
|
||||
};
|
||||
return Type{ .ptr_otherwise = &new_payload.base };
|
||||
},
|
||||
.single_const_pointer => {
|
||||
const payload = @fieldParentPtr(Payload.SingleConstPointer, "base", self.ptr_otherwise);
|
||||
const new_payload = try allocator.create(Payload.SingleConstPointer);
|
||||
new_payload.* = .{
|
||||
.base = payload.base,
|
||||
.pointee_type = try payload.pointee_type.copy(allocator),
|
||||
};
|
||||
return Type{ .ptr_otherwise = &new_payload.base };
|
||||
},
|
||||
.single_mut_pointer => {
|
||||
const payload = @fieldParentPtr(Payload.SingleMutPointer, "base", self.ptr_otherwise);
|
||||
const new_payload = try allocator.create(Payload.SingleMutPointer);
|
||||
new_payload.* = .{
|
||||
.base = payload.base,
|
||||
.pointee_type = try payload.pointee_type.copy(allocator),
|
||||
};
|
||||
return Type{ .ptr_otherwise = &new_payload.base };
|
||||
},
|
||||
.single_const_pointer => return self.copyPayloadSingleField(allocator, Payload.SingleConstPointer, "pointee_type"),
|
||||
.single_mut_pointer => return self.copyPayloadSingleField(allocator, Payload.SingleMutPointer, "pointee_type"),
|
||||
.int_signed => return self.copyPayloadShallow(allocator, Payload.IntSigned),
|
||||
.int_unsigned => return self.copyPayloadShallow(allocator, Payload.IntUnsigned),
|
||||
.function => {
|
||||
@@ -352,6 +347,9 @@ pub const Type = extern union {
|
||||
};
|
||||
return Type{ .ptr_otherwise = &new_payload.base };
|
||||
},
|
||||
.optional => return self.copyPayloadSingleField(allocator, Payload.Optional, "child_type"),
|
||||
.optional_single_mut_pointer => return self.copyPayloadSingleField(allocator, Payload.OptionalSingleMutPointer, "pointee_type"),
|
||||
.optional_single_const_pointer => return self.copyPayloadSingleField(allocator, Payload.OptionalSingleConstPointer, "pointee_type"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,6 +360,14 @@ pub const Type = extern union {
|
||||
return Type{ .ptr_otherwise = &new_payload.base };
|
||||
}
|
||||
|
||||
fn copyPayloadSingleField(self: Type, allocator: *Allocator, comptime T: type, comptime field_name: []const u8) error{OutOfMemory}!Type {
|
||||
const payload = @fieldParentPtr(T, "base", self.ptr_otherwise);
|
||||
const new_payload = try allocator.create(T);
|
||||
new_payload.base = payload.base;
|
||||
@field(new_payload, field_name) = try @field(payload, field_name).copy(allocator);
|
||||
return Type{ .ptr_otherwise = &new_payload.base };
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
self: Type,
|
||||
comptime fmt: []const u8,
|
||||
@@ -456,6 +462,24 @@ pub const Type = extern union {
|
||||
const payload = @fieldParentPtr(Payload.IntUnsigned, "base", ty.ptr_otherwise);
|
||||
return out_stream.print("u{}", .{payload.bits});
|
||||
},
|
||||
.optional => {
|
||||
const payload = @fieldParentPtr(Payload.Optional, "base", ty.ptr_otherwise);
|
||||
try out_stream.writeByte('?');
|
||||
ty = payload.child_type;
|
||||
continue;
|
||||
},
|
||||
.optional_single_const_pointer => {
|
||||
const payload = @fieldParentPtr(Payload.OptionalSingleConstPointer, "base", ty.ptr_otherwise);
|
||||
try out_stream.writeAll("?*const ");
|
||||
ty = payload.pointee_type;
|
||||
continue;
|
||||
},
|
||||
.optional_single_mut_pointer => {
|
||||
const payload = @fieldParentPtr(Payload.OptionalSingleMutPointer, "base", ty.ptr_otherwise);
|
||||
try out_stream.writeAll("?*");
|
||||
ty = payload.pointee_type;
|
||||
continue;
|
||||
},
|
||||
}
|
||||
unreachable;
|
||||
}
|
||||
@@ -545,11 +569,15 @@ pub const Type = extern union {
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.const_slice_u8,
|
||||
.array_u8_sentinel_0,
|
||||
.array, // TODO check for zero bits
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.int_signed, // TODO check for zero bits
|
||||
.int_unsigned, // TODO check for zero bits
|
||||
// TODO lazy types
|
||||
.array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
|
||||
.single_const_pointer => self.elemType().hasCodeGenBits(),
|
||||
.single_mut_pointer => self.elemType().hasCodeGenBits(),
|
||||
.int_signed => self.cast(Payload.IntSigned).?.bits == 0,
|
||||
.int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> true,
|
||||
|
||||
.c_void,
|
||||
@@ -597,6 +625,8 @@ pub const Type = extern union {
|
||||
.const_slice_u8,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
.optional_single_mut_pointer,
|
||||
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
|
||||
.c_short => return @divExact(CType.short.sizeInBits(target), 8),
|
||||
@@ -629,6 +659,12 @@ pub const Type = extern union {
|
||||
return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
|
||||
},
|
||||
|
||||
.optional => {
|
||||
const child_type = self.cast(Payload.Optional).?.child_type;
|
||||
if (!child_type.hasCodeGenBits()) return 1;
|
||||
return child_type.abiAlignment(target);
|
||||
},
|
||||
|
||||
.c_void,
|
||||
.void,
|
||||
.type,
|
||||
@@ -679,6 +715,8 @@ pub const Type = extern union {
|
||||
.const_slice_u8,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
.optional_single_mut_pointer,
|
||||
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
|
||||
|
||||
.c_short => return @divExact(CType.short.sizeInBits(target), 8),
|
||||
@@ -708,6 +746,16 @@ pub const Type = extern union {
|
||||
|
||||
return std.math.ceilPowerOfTwoPromote(u16, (bits + 7) / 8);
|
||||
},
|
||||
|
||||
.optional => {
|
||||
const child_type = self.cast(Payload.Optional).?.child_type;
|
||||
if (!child_type.hasCodeGenBits()) return 1;
|
||||
// Optional types are represented as a struct with the child type as the first
|
||||
// field and a boolean as the second. Since the child type's abi alignment is
|
||||
// guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
|
||||
// to the child type's ABI alignment.
|
||||
return child_type.abiAlignment(target) + child_type.abiSize(target);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -756,6 +804,9 @@ pub const Type = extern union {
|
||||
.function,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> false,
|
||||
|
||||
.single_const_pointer,
|
||||
@@ -812,6 +863,9 @@ pub const Type = extern union {
|
||||
.function,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> false,
|
||||
|
||||
.const_slice_u8 => true,
|
||||
@@ -863,6 +917,9 @@ pub const Type = extern union {
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.single_mut_pointer,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> false,
|
||||
|
||||
.single_const_pointer,
|
||||
@@ -920,11 +977,14 @@ pub const Type = extern union {
|
||||
.single_const_pointer,
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.const_slice_u8,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
|
||||
/// Asserts the type is a pointer or array type.
|
||||
/// Asserts the type is a pointer, optional or array type.
|
||||
pub fn elemType(self: Type) Type {
|
||||
return switch (self.tag()) {
|
||||
.u8,
|
||||
@@ -974,6 +1034,9 @@ pub const Type = extern union {
|
||||
.single_mut_pointer => self.cast(Payload.SingleMutPointer).?.pointee_type,
|
||||
.array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
|
||||
.single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
|
||||
.optional => self.cast(Payload.Optional).?.child_type,
|
||||
.optional_single_mut_pointer => self.cast(Payload.OptionalSingleMutPointer).?.pointee_type,
|
||||
.optional_single_const_pointer => self.cast(Payload.OptionalSingleConstPointer).?.pointee_type,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1024,6 +1087,9 @@ pub const Type = extern union {
|
||||
.const_slice_u8,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
|
||||
.array => self.cast(Payload.Array).?.len,
|
||||
@@ -1078,6 +1144,9 @@ pub const Type = extern union {
|
||||
.const_slice_u8,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
|
||||
.array => return null,
|
||||
@@ -1129,6 +1198,9 @@ pub const Type = extern union {
|
||||
.u16,
|
||||
.u32,
|
||||
.u64,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> false,
|
||||
|
||||
.int_signed,
|
||||
@@ -1184,6 +1256,9 @@ pub const Type = extern union {
|
||||
.i16,
|
||||
.i32,
|
||||
.i64,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> false,
|
||||
|
||||
.int_unsigned,
|
||||
@@ -1229,6 +1304,9 @@ pub const Type = extern union {
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.array_u8_sentinel_0,
|
||||
.const_slice_u8,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
|
||||
.int_unsigned => .{ .signed = false, .bits = self.cast(Payload.IntUnsigned).?.bits },
|
||||
@@ -1292,6 +1370,9 @@ pub const Type = extern union {
|
||||
.i32,
|
||||
.u64,
|
||||
.i64,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> false,
|
||||
|
||||
.usize,
|
||||
@@ -1384,6 +1465,9 @@ pub const Type = extern union {
|
||||
.c_ulonglong,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
};
|
||||
}
|
||||
@@ -1442,6 +1526,9 @@ pub const Type = extern union {
|
||||
.c_ulonglong,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
}
|
||||
}
|
||||
@@ -1499,6 +1586,9 @@ pub const Type = extern union {
|
||||
.c_ulonglong,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
}
|
||||
}
|
||||
@@ -1556,6 +1646,9 @@ pub const Type = extern union {
|
||||
.c_ulonglong,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
};
|
||||
}
|
||||
@@ -1610,6 +1703,9 @@ pub const Type = extern union {
|
||||
.c_ulonglong,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
};
|
||||
}
|
||||
@@ -1664,6 +1760,9 @@ pub const Type = extern union {
|
||||
.c_ulonglong,
|
||||
.int_unsigned,
|
||||
.int_signed,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> unreachable,
|
||||
};
|
||||
}
|
||||
@@ -1718,6 +1817,9 @@ pub const Type = extern union {
|
||||
.single_const_pointer_to_comptime_int,
|
||||
.array_u8_sentinel_0,
|
||||
.const_slice_u8,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
@@ -1762,6 +1864,9 @@ pub const Type = extern union {
|
||||
.array_u8_sentinel_0,
|
||||
.const_slice_u8,
|
||||
.c_void,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> return null,
|
||||
|
||||
.void => return Value.initTag(.void_value),
|
||||
@@ -1851,6 +1956,9 @@ pub const Type = extern union {
|
||||
.array,
|
||||
.single_const_pointer,
|
||||
.single_mut_pointer,
|
||||
.optional,
|
||||
.optional_single_mut_pointer,
|
||||
.optional_single_const_pointer,
|
||||
=> return false,
|
||||
};
|
||||
}
|
||||
@@ -1911,6 +2019,9 @@ pub const Type = extern union {
|
||||
int_signed,
|
||||
int_unsigned,
|
||||
function,
|
||||
optional,
|
||||
optional_single_mut_pointer,
|
||||
optional_single_const_pointer,
|
||||
|
||||
pub const last_no_payload_tag = Tag.const_slice_u8;
|
||||
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
|
||||
@@ -1963,6 +2074,24 @@ pub const Type = extern union {
|
||||
return_type: Type,
|
||||
cc: std.builtin.CallingConvention,
|
||||
};
|
||||
|
||||
pub const Optional = struct {
|
||||
base: Payload = Payload{ .tag = .optional },
|
||||
|
||||
child_type: Type,
|
||||
};
|
||||
|
||||
pub const OptionalSingleConstPointer = struct {
|
||||
base: Payload = Payload{ .tag = .optional_single_const_pointer },
|
||||
|
||||
pointee_type: Type,
|
||||
};
|
||||
|
||||
pub const OptionalSingleMutPointer = struct {
|
||||
base: Payload = Payload{ .tag = .optional_single_mut_pointer },
|
||||
|
||||
pointee_type: Type,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user