...
This commit is contained in:
195
src/types.zig
195
src/types.zig
@@ -98,49 +98,65 @@ pub const Type = union(enum) {
|
||||
}
|
||||
|
||||
pub fn fromName(name: []const u8) ?Type {
|
||||
// Named types (check before variable-width integers since "string" starts with 's')
|
||||
if (std.mem.eql(u8, name, "string")) return .string_type;
|
||||
if (std.mem.eql(u8, name, "bool")) return .boolean;
|
||||
if (std.mem.eql(u8, name, "f32")) return .f32;
|
||||
if (std.mem.eql(u8, name, "f64")) return .f64;
|
||||
if (std.mem.eql(u8, name, "Any")) return .any_type;
|
||||
// Sentinel-terminated slice: [:0]T → string_type when T is u8
|
||||
if (name.len >= 5 and name[0] == '[' and name[1] == ':') {
|
||||
// Find closing ']'
|
||||
if (std.mem.indexOfScalar(u8, name, ']')) |close| {
|
||||
const sentinel = name[2..close];
|
||||
const elem = name[close + 1 ..];
|
||||
if (std.mem.eql(u8, sentinel, "0") and std.mem.eql(u8, elem, "u8")) {
|
||||
return .string_type;
|
||||
if (name.len == 0) return null;
|
||||
return switch (name[0]) {
|
||||
's' => {
|
||||
if (std.mem.eql(u8, name, "string")) return .string_type;
|
||||
if (name.len >= 2) {
|
||||
const width = std.fmt.parseInt(u8, name[1..], 10) catch return null;
|
||||
if (width >= 1 and width <= 64) return Type.s(width);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Many-pointer: [*]T
|
||||
if (name.len >= 4 and name[0] == '[' and name[1] == '*' and name[2] == ']') {
|
||||
return .{ .many_pointer_type = .{ .element_name = name[3..] } };
|
||||
}
|
||||
// Pointer: *T
|
||||
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 } };
|
||||
return null;
|
||||
},
|
||||
'u' => {
|
||||
if (name.len >= 2) {
|
||||
const width = std.fmt.parseInt(u8, name[1..], 10) catch return null;
|
||||
if (width >= 1 and width <= 64) return Type.u(width);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
if (width < 1 or width > 64) return null;
|
||||
return if (name[0] == 's') Type.s(width) else Type.u(width);
|
||||
}
|
||||
return null;
|
||||
return null;
|
||||
},
|
||||
'b' => if (std.mem.eql(u8, name, "bool")) .boolean else null,
|
||||
'f' => {
|
||||
if (std.mem.eql(u8, name, "f32")) return .f32;
|
||||
if (std.mem.eql(u8, name, "f64")) return .f64;
|
||||
return null;
|
||||
},
|
||||
'A' => if (std.mem.eql(u8, name, "Any")) .any_type else null,
|
||||
'v' => if (std.mem.eql(u8, name, "void")) .void_type else null,
|
||||
'[' => {
|
||||
// Sentinel-terminated slice: [:0]u8 → string_type
|
||||
if (name.len >= 5 and name[1] == ':') {
|
||||
if (std.mem.indexOfScalar(u8, name, ']')) |close| {
|
||||
const sentinel = name[2..close];
|
||||
const elem = name[close + 1 ..];
|
||||
if (std.mem.eql(u8, sentinel, "0") and std.mem.eql(u8, elem, "u8")) {
|
||||
return .string_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Many-pointer: [*]T
|
||||
if (name.len >= 4 and name[1] == '*' and name[2] == ']') {
|
||||
return .{ .many_pointer_type = .{ .element_name = name[3..] } };
|
||||
}
|
||||
return null;
|
||||
},
|
||||
'*' => if (name.len >= 2) .{ .pointer_type = .{ .pointee_name = name[1..] } } else null,
|
||||
'V' => {
|
||||
// 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];
|
||||
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 } };
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fromTypeExpr(node: *Node) ?Type {
|
||||
@@ -363,20 +379,14 @@ pub const Type = union(enum) {
|
||||
pub fn displayName(self: Type, allocator: std.mem.Allocator) ![]const u8 {
|
||||
return switch (self) {
|
||||
.signed => |w| {
|
||||
var buf = std.ArrayList(u8).empty;
|
||||
try buf.append(allocator, 's');
|
||||
var tmp: [4]u8 = undefined;
|
||||
const width_str = std.fmt.bufPrint(&tmp, "{d}", .{w}) catch unreachable;
|
||||
try buf.appendSlice(allocator, width_str);
|
||||
return try buf.toOwnedSlice(allocator);
|
||||
var buf: [4]u8 = undefined;
|
||||
const result = std.fmt.bufPrint(&buf, "s{d}", .{w}) catch unreachable;
|
||||
return try allocator.dupe(u8, result);
|
||||
},
|
||||
.unsigned => |w| {
|
||||
var buf = std.ArrayList(u8).empty;
|
||||
try buf.append(allocator, 'u');
|
||||
var tmp: [4]u8 = undefined;
|
||||
const width_str = std.fmt.bufPrint(&tmp, "{d}", .{w}) catch unreachable;
|
||||
try buf.appendSlice(allocator, width_str);
|
||||
return try buf.toOwnedSlice(allocator);
|
||||
var buf: [4]u8 = undefined;
|
||||
const result = std.fmt.bufPrint(&buf, "u{d}", .{w}) catch unreachable;
|
||||
return try allocator.dupe(u8, result);
|
||||
},
|
||||
.f32 => "f32",
|
||||
.f64 => "f64",
|
||||
@@ -388,43 +398,64 @@ pub const Type = union(enum) {
|
||||
.struct_type => |name| name,
|
||||
.union_type => |name| name,
|
||||
.slice_type => |info| {
|
||||
var buf = std.ArrayList(u8).empty;
|
||||
try buf.appendSlice(allocator, "[]");
|
||||
try buf.appendSlice(allocator, info.element_name);
|
||||
return try buf.toOwnedSlice(allocator);
|
||||
var buf: [128]u8 = undefined;
|
||||
const result = std.fmt.bufPrint(&buf, "[]{s}", .{info.element_name}) catch {
|
||||
// Fall back to dynamic allocation for very long element names
|
||||
var dyn = std.ArrayList(u8).empty;
|
||||
try dyn.appendSlice(allocator, "[]");
|
||||
try dyn.appendSlice(allocator, info.element_name);
|
||||
return try dyn.toOwnedSlice(allocator);
|
||||
};
|
||||
return try allocator.dupe(u8, result);
|
||||
},
|
||||
.pointer_type => |info| {
|
||||
var buf = std.ArrayList(u8).empty;
|
||||
try buf.append(allocator, '*');
|
||||
try buf.appendSlice(allocator, info.pointee_name);
|
||||
return try buf.toOwnedSlice(allocator);
|
||||
var buf: [128]u8 = undefined;
|
||||
const result = std.fmt.bufPrint(&buf, "*{s}", .{info.pointee_name}) catch {
|
||||
var dyn = std.ArrayList(u8).empty;
|
||||
try dyn.appendSlice(allocator, "*");
|
||||
try dyn.appendSlice(allocator, info.pointee_name);
|
||||
return try dyn.toOwnedSlice(allocator);
|
||||
};
|
||||
return try allocator.dupe(u8, result);
|
||||
},
|
||||
.many_pointer_type => |info| {
|
||||
var buf = std.ArrayList(u8).empty;
|
||||
try buf.appendSlice(allocator, "[*]");
|
||||
try buf.appendSlice(allocator, info.element_name);
|
||||
return try buf.toOwnedSlice(allocator);
|
||||
var buf: [128]u8 = undefined;
|
||||
const result = std.fmt.bufPrint(&buf, "[*]{s}", .{info.element_name}) catch {
|
||||
var dyn = std.ArrayList(u8).empty;
|
||||
try dyn.appendSlice(allocator, "[*]");
|
||||
try dyn.appendSlice(allocator, info.element_name);
|
||||
return try dyn.toOwnedSlice(allocator);
|
||||
};
|
||||
return try allocator.dupe(u8, result);
|
||||
},
|
||||
.array_type => |info| {
|
||||
var buf = std.ArrayList(u8).empty;
|
||||
try buf.append(allocator, '[');
|
||||
var tmp: [10]u8 = undefined;
|
||||
const len_str = std.fmt.bufPrint(&tmp, "{d}", .{info.length}) catch unreachable;
|
||||
try buf.appendSlice(allocator, len_str);
|
||||
try buf.append(allocator, ']');
|
||||
try buf.appendSlice(allocator, info.element_name);
|
||||
return try buf.toOwnedSlice(allocator);
|
||||
var buf: [128]u8 = undefined;
|
||||
const result = std.fmt.bufPrint(&buf, "[{d}]{s}", .{ info.length, info.element_name }) catch {
|
||||
var dyn = std.ArrayList(u8).empty;
|
||||
try dyn.appendSlice(allocator, "[");
|
||||
var tmp: [10]u8 = undefined;
|
||||
const len_str = std.fmt.bufPrint(&tmp, "{d}", .{info.length}) catch unreachable;
|
||||
try dyn.appendSlice(allocator, len_str);
|
||||
try dyn.appendSlice(allocator, "]");
|
||||
try dyn.appendSlice(allocator, info.element_name);
|
||||
return try dyn.toOwnedSlice(allocator);
|
||||
};
|
||||
return try allocator.dupe(u8, result);
|
||||
},
|
||||
.vector_type => |info| {
|
||||
var buf = std.ArrayList(u8).empty;
|
||||
try buf.appendSlice(allocator, "Vector(");
|
||||
var tmp: [10]u8 = undefined;
|
||||
const len_str = std.fmt.bufPrint(&tmp, "{d}", .{info.length}) catch unreachable;
|
||||
try buf.appendSlice(allocator, len_str);
|
||||
try buf.appendSlice(allocator, ",");
|
||||
try buf.appendSlice(allocator, info.element_name);
|
||||
try buf.append(allocator, ')');
|
||||
return try buf.toOwnedSlice(allocator);
|
||||
var buf: [128]u8 = undefined;
|
||||
const result = std.fmt.bufPrint(&buf, "Vector({d},{s})", .{ info.length, info.element_name }) catch {
|
||||
var dyn = std.ArrayList(u8).empty;
|
||||
try dyn.appendSlice(allocator, "Vector(");
|
||||
var tmp: [10]u8 = undefined;
|
||||
const len_str = std.fmt.bufPrint(&tmp, "{d}", .{info.length}) catch unreachable;
|
||||
try dyn.appendSlice(allocator, len_str);
|
||||
try dyn.appendSlice(allocator, ",");
|
||||
try dyn.appendSlice(allocator, info.element_name);
|
||||
try dyn.appendSlice(allocator, ")");
|
||||
return try dyn.toOwnedSlice(allocator);
|
||||
};
|
||||
return try allocator.dupe(u8, result);
|
||||
},
|
||||
.function_type => |info| {
|
||||
var buf = std.ArrayList(u8).empty;
|
||||
|
||||
Reference in New Issue
Block a user