sdl phase 2
This commit is contained in:
@@ -56,6 +56,38 @@ pub const Type = union(enum) {
|
||||
name: []const u8,
|
||||
};
|
||||
|
||||
/// Content-based equality: compares string fields by content, not pointer identity.
|
||||
pub fn eql(self: Type, other: Type) bool {
|
||||
const Tag = std.meta.Tag(Type);
|
||||
const self_tag: Tag = self;
|
||||
const other_tag: Tag = other;
|
||||
if (self_tag != other_tag) return false;
|
||||
return switch (self) {
|
||||
.signed => |w| w == other.signed,
|
||||
.unsigned => |w| w == other.unsigned,
|
||||
.f32, .f64, .void_type, .boolean, .string_type, .any_type => true,
|
||||
.enum_type => |n| std.mem.eql(u8, n, other.enum_type),
|
||||
.struct_type => |n| std.mem.eql(u8, n, other.struct_type),
|
||||
.union_type => |n| std.mem.eql(u8, n, other.union_type),
|
||||
.array_type => |info| info.length == other.array_type.length and
|
||||
std.mem.eql(u8, info.element_name, other.array_type.element_name),
|
||||
.slice_type => |info| std.mem.eql(u8, info.element_name, other.slice_type.element_name),
|
||||
.pointer_type => |info| std.mem.eql(u8, info.pointee_name, other.pointer_type.pointee_name),
|
||||
.many_pointer_type => |info| std.mem.eql(u8, info.element_name, other.many_pointer_type.element_name),
|
||||
.vector_type => |info| info.length == other.vector_type.length and
|
||||
std.mem.eql(u8, info.element_name, other.vector_type.element_name),
|
||||
.function_type => |info| {
|
||||
const o = other.function_type;
|
||||
if (info.param_types.len != o.param_types.len) return false;
|
||||
for (info.param_types, o.param_types) |a, b| {
|
||||
if (!a.eql(b)) return false;
|
||||
}
|
||||
return info.return_type.eql(o.return_type.*);
|
||||
},
|
||||
.meta_type => |info| std.mem.eql(u8, info.name, other.meta_type.name),
|
||||
};
|
||||
}
|
||||
|
||||
// Convenience constructors
|
||||
pub fn s(width: u8) Type {
|
||||
return .{ .signed = width };
|
||||
@@ -91,6 +123,17 @@ pub const Type = union(enum) {
|
||||
if (name.len >= 2 and name[0] == '*') {
|
||||
return .{ .pointer_type = .{ .pointee_name = name[1..] } };
|
||||
}
|
||||
// Vector: Vector(N,T)
|
||||
if (name.len >= 10 and std.mem.startsWith(u8, name, "Vector(") and name[name.len - 1] == ')') {
|
||||
const inner = name[7 .. name.len - 1]; // contents between ( and )
|
||||
if (std.mem.indexOfScalar(u8, inner, ',')) |comma| {
|
||||
const length = std.fmt.parseInt(u32, inner[0..comma], 10) catch return null;
|
||||
const elem_name = inner[comma + 1 ..];
|
||||
if (elem_name.len > 0) {
|
||||
return .{ .vector_type = .{ .element_name = elem_name, .length = length } };
|
||||
}
|
||||
}
|
||||
}
|
||||
// Variable-width integers: s1..s64, u1..u64
|
||||
if (name.len >= 2 and (name[0] == 's' or name[0] == 'u')) {
|
||||
const width = std.fmt.parseInt(u8, name[1..], 10) catch return null;
|
||||
@@ -263,29 +306,16 @@ pub const Type = union(enum) {
|
||||
/// - Float to wider float (f32 → f64)
|
||||
/// Everything else requires `xx`.
|
||||
pub fn isImplicitlyConvertibleTo(self: Type, target: Type) bool {
|
||||
if (std.meta.eql(self, target)) return true;
|
||||
// Struct types: compare names by content (not pointer identity)
|
||||
if (self.isStruct() and target.isStruct()) {
|
||||
return std.mem.eql(u8, self.struct_type, target.struct_type);
|
||||
}
|
||||
// Slice types: compare element names by content (not pointer)
|
||||
if (self.isSlice() and target.isSlice()) {
|
||||
return std.mem.eql(u8, self.slice_type.element_name, target.slice_type.element_name);
|
||||
}
|
||||
if (self.eql(target)) return true;
|
||||
// string <-> []u8: same layout, bidirectional implicit conversion
|
||||
if (self == .string_type and target.isSlice() and
|
||||
std.mem.eql(u8, target.slice_type.element_name, "u8")) return true;
|
||||
if (self.isSlice() and std.mem.eql(u8, self.slice_type.element_name, "u8") and
|
||||
target == .string_type) return true;
|
||||
// Pointer types: compare pointee names by content, *void is universal (both directions)
|
||||
// *void is universal pointer (both directions)
|
||||
if (self.isPointer() and target.isPointer()) {
|
||||
if (std.mem.eql(u8, self.pointer_type.pointee_name, "void")) return true;
|
||||
if (std.mem.eql(u8, target.pointer_type.pointee_name, "void")) return true;
|
||||
return std.mem.eql(u8, self.pointer_type.pointee_name, target.pointer_type.pointee_name);
|
||||
}
|
||||
// Many-pointer types: compare element names by content
|
||||
if (self.isManyPointer() and target.isManyPointer()) {
|
||||
return std.mem.eql(u8, self.many_pointer_type.element_name, target.many_pointer_type.element_name);
|
||||
}
|
||||
// *T → [*]T: pointer to element is implicitly convertible to many-pointer
|
||||
// null (*void) → [*]T is also allowed
|
||||
@@ -418,7 +448,7 @@ pub const Type = union(enum) {
|
||||
/// Used for arithmetic type promotion (e.g., s16 + s32 → s32, int + float → float).
|
||||
pub fn widen(a: Type, b: Type) Type {
|
||||
// Same type → return it
|
||||
if (std.meta.eql(a, b)) return a;
|
||||
if (a.eql(b)) return a;
|
||||
|
||||
// Vector + vector of same dimensions → return a
|
||||
if (a.isVector() and b.isVector()) return a;
|
||||
|
||||
Reference in New Issue
Block a user