refactor type printing

This commit is contained in:
Techatrix 2023-01-17 20:23:27 +01:00
parent 739bd08b7b
commit 407f921ef8
4 changed files with 69 additions and 44 deletions

View File

@ -256,7 +256,7 @@ pub fn interpret(
try interpreter.recordError( try interpreter.recordError(
container_field.ast.type_expr, container_field.ast.type_expr,
"expected_type", "expected_type",
try std.fmt.allocPrint(interpreter.allocator, "expected type 'type', found '{}'", .{init_type_value.ty.fmtType(&interpreter.ip)}), try std.fmt.allocPrint(interpreter.allocator, "expected type 'type', found '{}'", .{init_type_value.ty.fmtType(interpreter.ip)}),
); );
continue; continue;
} }
@ -623,7 +623,7 @@ pub fn interpret(
try writer.writeAll("indeterminate"); try writer.writeAll("indeterminate");
continue; continue;
}; };
try writer.print("@as({}, {})", .{ value.ty.fmtType(&interpreter.ip), value.val.fmtValue(value.ty, &interpreter.ip) }); try writer.print("@as({}, {})", .{ value.ty.fmtType(interpreter.ip), value.val.fmtValue(value.ty, interpreter.ip) });
if (index != params.len - 1) if (index != params.len - 1)
try writer.writeAll(", "); try writer.writeAll(", ");
} }
@ -981,7 +981,7 @@ pub fn call(
try interpreter.recordError( try interpreter.recordError(
param.type_expr, param.type_expr,
"expected_type", "expected_type",
std.fmt.allocPrint(interpreter.allocator, "expected type 'type', found '{}'", .{tex.ty.fmtType(&interpreter.ip)}) catch return error.CriticalAstFailure, std.fmt.allocPrint(interpreter.allocator, "expected type 'type', found '{}'", .{tex.ty.fmtType(interpreter.ip)}) catch return error.CriticalAstFailure,
); );
return error.InvalidCast; return error.InvalidCast;
} }

View File

@ -419,16 +419,17 @@ pub const Key = union(enum) {
} }
pub const TypeFormatContext = struct { pub const TypeFormatContext = struct {
ty: Index, ty: Key,
options: FormatOptions = .{}, options: FormatOptions = .{},
ip: *const InternPool, ip: InternPool,
}; };
pub const ValueFormatContext = struct { pub const ValueFormatContext = struct {
value: Index, value: Key,
/// for most values the type is not needed which is why we use an index
ty: Index, ty: Index,
options: FormatOptions = .{}, options: FormatOptions = .{},
ip: *const InternPool, ip: InternPool,
}; };
// TODO implement options // TODO implement options
@ -437,20 +438,30 @@ pub const Key = union(enum) {
include_declarations: bool = true, include_declarations: bool = true,
}; };
pub fn formatType( fn formatType(
ctx: TypeFormatContext, ctx: TypeFormatContext,
comptime unused_format_string: []const u8, comptime fmt: []const u8,
options: std.fmt.FormatOptions, options: std.fmt.FormatOptions,
writer: anytype, writer: anytype,
) @TypeOf(writer).Error!void { ) @TypeOf(writer).Error!void {
comptime assert(unused_format_string.len == 0);
_ = options; _ = options;
return printType(ctx.ty, ctx.ip, writer); if (fmt.len != 0) std.fmt.invalidFmtError(fmt, Key);
try printTypeKey(ctx.ty, ctx.ip, writer);
} }
pub fn printType(ty: Index, ip: *const InternPool, writer: anytype) @TypeOf(writer).Error!void { fn printType(ty: Index, ip: InternPool, writer: anytype) @TypeOf(writer).Error!void {
const key: Key = ip.indexToKey(ty); try printTypeKey(ip.indexToKey(ty), ip, writer);
switch (key) { }
fn printTypeKey(ty: Key, ip: InternPool, writer: anytype) @TypeOf(writer).Error!void {
var key = ty;
while (try printTypeInternal(key, ip, writer)) |index| {
key = ip.indexToKey(index);
}
}
fn printTypeInternal(ty: Key, ip: InternPool, writer: anytype) @TypeOf(writer).Error!?Index {
switch (ty) {
.simple => |simple| switch (simple) { .simple => |simple| switch (simple) {
.f16, .f16,
.f32, .f32,
@ -527,7 +538,7 @@ pub const Key = union(enum) {
if (pointer_info.is_volatile) try writer.writeAll("volatile "); if (pointer_info.is_volatile) try writer.writeAll("volatile ");
if (pointer_info.is_allowzero and pointer_info.size != .C) try writer.writeAll("allowzero "); if (pointer_info.is_allowzero and pointer_info.size != .C) try writer.writeAll("allowzero ");
try printType(pointer_info.elem_type, ip, writer); return pointer_info.elem_type;
}, },
.array_type => |array_info| { .array_type => |array_info| {
try writer.print("[{d}", .{array_info.len}); try writer.print("[{d}", .{array_info.len});
@ -535,18 +546,18 @@ pub const Key = union(enum) {
try writer.print(":{}", .{array_info.sentinel.fmtValue(array_info.child, ip)}); try writer.print(":{}", .{array_info.sentinel.fmtValue(array_info.child, ip)});
} }
try writer.writeByte(']'); try writer.writeByte(']');
try printType(array_info.child, ip, writer);
return array_info.child;
}, },
.struct_type => @panic("TODO"), .struct_type => @panic("TODO"),
.optional_type => |optional_info| { .optional_type => |optional_info| {
try writer.writeByte('?'); try writer.writeByte('?');
try printType(optional_info.payload_type, ip, writer); return optional_info.payload_type;
}, },
.error_union_type => |error_union_info| { .error_union_type => |error_union_info| {
try writer.print("{}!{}", .{ try printType(error_union_info.error_set_type, ip, writer);
error_union_info.error_set_type.fmtType(ip), try writer.writeByte('!');
error_union_info.payload_type.fmtType(ip), return error_union_info.payload_type;
});
}, },
.error_set_type => |error_set_info| { .error_set_type => |error_set_info| {
const names = error_set_info.names; const names = error_set_info.names;
@ -585,10 +596,8 @@ pub const Key = union(enum) {
if (function_info.calling_convention != .Unspecified) { if (function_info.calling_convention != .Unspecified) {
try writer.print("callconv(.{s}) ", .{@tagName(function_info.calling_convention)}); try writer.print("callconv(.{s}) ", .{@tagName(function_info.calling_convention)});
} }
if (function_info.alignment != 0) {
try writer.print("align({d}) ", .{function_info.alignment}); return function_info.return_type;
}
try printType(function_info.return_type, ip, writer);
}, },
.union_type => @panic("TODO"), .union_type => @panic("TODO"),
.tuple_type => |tuple_info| { .tuple_type => |tuple_info| {
@ -614,7 +623,7 @@ pub const Key = union(enum) {
}, },
.anyframe_type => |anyframe_info| { .anyframe_type => |anyframe_info| {
try writer.writeAll("anyframe->"); try writer.writeAll("anyframe->");
try printType(anyframe_info.child, ip, writer); return anyframe_info.child;
}, },
.int_u64_value, .int_u64_value,
@ -632,27 +641,28 @@ pub const Key = union(enum) {
.union_value, .union_value,
=> unreachable, => unreachable,
} }
return null;
} }
pub fn formatValue( fn formatValue(
ctx: ValueFormatContext, ctx: ValueFormatContext,
comptime unused_format_string: []const u8, comptime fmt: []const u8,
options: std.fmt.FormatOptions, options: std.fmt.FormatOptions,
writer: anytype, writer: anytype,
) @TypeOf(writer).Error!void { ) @TypeOf(writer).Error!void {
comptime assert(unused_format_string.len == 0); comptime assert(fmt.len == 0);
_ = options; _ = options;
if (fmt.len != 0) std.fmt.invalidFmtError(fmt, Key);
return printValue(ctx.value, ctx.ty, ctx.ip, writer); return printValue(ctx.value, ctx.ty, ctx.ip, writer);
} }
pub fn printValue( fn printValue(
value: Index, value: Key,
ty: Index, ty: Index,
ip: *const InternPool, ip: InternPool,
writer: anytype, writer: anytype,
) @TypeOf(writer).Error!void { ) @TypeOf(writer).Error!void {
const value_key: Key = ip.indexToKey(value); switch (value) {
switch (value_key) {
.simple => |simple| switch (simple) { .simple => |simple| switch (simple) {
.f16, .f16,
.f32, .f32,
@ -729,7 +739,7 @@ pub const Key = union(enum) {
if (i != 0) try writer.writeAll(", "); if (i != 0) try writer.writeAll(", ");
try writer.print(".{s} = ", .{struct_info.fields[i].name}); try writer.print(".{s} = ", .{struct_info.fields[i].name});
try printValue(aggregate[i], struct_info.fields[i].ty, ip, writer); try printValue(ip.indexToKey(aggregate[i]), struct_info.fields[i].ty, ip, writer);
} }
try writer.writeByte('}'); try writer.writeByte('}');
}, },
@ -737,13 +747,28 @@ pub const Key = union(enum) {
const union_info = ip.indexToKey(ty).union_type; const union_info = ip.indexToKey(ty).union_type;
try writer.writeAll(".{ "); try writer.writeAll(".{ ");
try printValue(union_info.tag_type, union_value.tag, ip, writer); try printValue(ip.indexToKey(union_info.tag_type), union_value.tag, ip, writer);
try writer.writeAll(" = "); try writer.writeAll(" = ");
try printValue(union_value.val, @panic("TODO"), ip, writer); try printValue(union_value.val, @panic("TODO"), ip, writer);
try writer.writeAll(" }"); try writer.writeAll(" }");
}, },
} }
} }
pub fn fmtType(ty: Key, ip: InternPool) std.fmt.Formatter(formatType) {
return .{ .data = .{
.ty = ty,
.ip = ip,
} };
}
pub fn fmtValue(value: Key, ty: Index, ip: InternPool) std.fmt.Formatter(formatValue) {
return .{ .data = .{
.value = value,
.ty = ty,
.ip = ip,
} };
}
}; };
pub const Item = struct { pub const Item = struct {
@ -761,16 +786,16 @@ pub const Index = enum(u32) {
none = std.math.maxInt(u32), none = std.math.maxInt(u32),
_, _,
pub fn fmtType(ty: Index, ip: *const InternPool) std.fmt.Formatter(Key.formatType) { pub fn fmtType(ty: Index, ip: InternPool) std.fmt.Formatter(Key.formatType) {
return .{ .data = .{ return .{ .data = .{
.ty = ty, .ty = ip.indexToKey(ty),
.ip = ip, .ip = ip,
} }; } };
} }
pub fn fmtValue(value_index: Index, type_index: Index, ip: *const InternPool) std.fmt.Formatter(Key.formatValue) { pub fn fmtValue(value_index: Index, type_index: Index, ip: InternPool) std.fmt.Formatter(Key.formatValue) {
return .{ .data = .{ return .{ .data = .{
.value = value_index, .value = ip.indexToKey(value_index),
.ty = type_index, .ty = type_index,
.ip = ip, .ip = ip,
} }; } };

View File

@ -583,7 +583,7 @@ fn typeToCompletion(
.primitive, .array_index => {}, .primitive, .array_index => {},
.@"comptime" => |co| { .@"comptime" => |co| {
const key = co.interpreter.ip.indexToKey(co.type.ty); const key = co.interpreter.ip.indexToKey(co.type.ty);
switch (key) { switch (key) {
.struct_type => |struct_info| { .struct_type => |struct_info| {
for (struct_info.fields) |field| { for (struct_info.fields) |field| {
@ -594,7 +594,7 @@ fn typeToCompletion(
.insertTextFormat = .PlainText, .insertTextFormat = .PlainText,
}); });
} }
// TODO declaration completion // TODO declaration completion
}, },
else => {}, else => {},
@ -916,7 +916,7 @@ fn hoverSymbol(server: *Server, decl_handle: analysis.DeclWithHandle) error{OutO
const resolved_type_str = if (resolved_type) |rt| const resolved_type_str = if (resolved_type) |rt|
if (rt.type.is_type_val) switch (rt.type.data) { if (rt.type.is_type_val) switch (rt.type.data) {
.@"comptime" => |*co| try std.fmt.allocPrint(server.arena.allocator(), "{}", .{co.type.ty.fmtType(&co.interpreter.ip)}), .@"comptime" => |*co| try std.fmt.allocPrint(server.arena.allocator(), "{}", .{co.type.ty.fmtType(co.interpreter.ip)}),
else => "type", else => "type",
} else switch (rt.type.data) { // TODO: Investigate random weird numbers like 897 that cause index of bounds } else switch (rt.type.data) { // TODO: Investigate random weird numbers like 897 that cause index of bounds
.pointer, .pointer,

View File

@ -793,7 +793,7 @@ pub fn resolveTypeOfNodeInternal(store: *DocumentStore, arena: *std.heap.ArenaAl
const type_type = try interpreter.ip.get(interpreter.allocator, ComptimeInterpreter.IPKey{ .simple = .type }); const type_type = try interpreter.ip.get(interpreter.allocator, ComptimeInterpreter.IPKey{ .simple = .type });
if (val.ty != type_type) { if (val.ty != type_type) {
log.err("Not a type: {}", .{val.ty.fmtType(&interpreter.ip)}); log.err("Not a type: {}", .{val.ty.fmtType(interpreter.ip)});
return null; return null;
} }