Skip to content

Commit

Permalink
Value: print with type
Browse files Browse the repository at this point in the history
  • Loading branch information
Vexu committed Nov 9, 2023
1 parent a27b536 commit e789edd
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 53 deletions.
28 changes: 14 additions & 14 deletions src/Attribute.zig
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ pub fn wantsAlignment(attr: Tag, idx: usize) bool {
}
}

pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Value, p: *Parser) !?Diagnostics.Message {
pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Parser.Result, p: *Parser) !?Diagnostics.Message {
switch (attr) {
inline else => |tag| {
const arg_fields = std.meta.fields(@field(attributes, @tagName(tag)));
Expand All @@ -202,12 +202,12 @@ pub fn diagnoseAlignment(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Va
inline 0...arg_fields.len - 1 => |arg_i| {
if (UnwrapOptional(arg_fields[arg_i].type) != Alignment) unreachable;

if (!val.is(.int, p.comp)) return Diagnostics.Message{ .tag = .alignas_unavailable };
if (val.compare(.lt, Value.zero, p.comp)) {
return Diagnostics.Message{ .tag = .negative_alignment, .extra = .{ .str = try p.valStr(val) } };
if (!res.val.is(.int, p.comp)) return Diagnostics.Message{ .tag = .alignas_unavailable };
if (res.val.compare(.lt, Value.zero, p.comp)) {
return Diagnostics.Message{ .tag = .negative_alignment, .extra = .{ .str = try res.str(p) } };
}
const requested = val.toInt(u29, p.comp) orelse {
return Diagnostics.Message{ .tag = .maximum_alignment, .extra = .{ .str = try p.valStr(val) } };
const requested = res.val.toInt(u29, p.comp) orelse {
return Diagnostics.Message{ .tag = .maximum_alignment, .extra = .{ .str = try res.str(p) } };
};
if (!std.mem.isValidAlign(requested)) return Diagnostics.Message{ .tag = .non_pow2_align };

Expand All @@ -225,24 +225,24 @@ fn diagnoseField(
comptime field: ZigType.StructField,
comptime Wanted: type,
arguments: *Arguments,
val: Value,
res: Parser.Result,
node: Tree.Node,
p: *Parser,
) !?Diagnostics.Message {
if (val.opt_ref == .none) {
if (res.val.opt_ref == .none) {
if (Wanted == Identifier and node.tag == .decl_ref_expr) {
@field(@field(arguments, decl.name), field.name) = Identifier{ .tok = node.data.decl_ref };
return null;
}
return invalidArgMsg(Wanted, .expression);
}
const key = p.comp.interner.get(val.ref());
const key = p.comp.interner.get(res.val.ref());
switch (key) {
.int => {
if (@typeInfo(Wanted) == .Int) {
@field(@field(arguments, decl.name), field.name) = val.toInt(Wanted, p.comp) orelse return .{
@field(@field(arguments, decl.name), field.name) = res.val.toInt(Wanted, p.comp) orelse return .{
.tag = .attribute_int_out_of_range,
.extra = .{ .str = try p.valStr(val) },
.extra = .{ .str = try res.str(p) },
};
return null;
}
Expand All @@ -256,7 +256,7 @@ fn diagnoseField(
.extra = .{ .str = decl.name },
};
}
@field(@field(arguments, decl.name), field.name) = try p.removeNull(val);
@field(@field(arguments, decl.name), field.name) = try p.removeNull(res.val);
return null;
} else if (@typeInfo(Wanted) == .Enum and @hasDecl(Wanted, "opts") and Wanted.opts.enum_kind == .string) {
const str = bytes[0 .. bytes.len - 1];
Expand Down Expand Up @@ -300,7 +300,7 @@ fn invalidArgMsg(comptime Expected: type, actual: ArgumentType) Diagnostics.Mess
};
}

pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Value, node: Tree.Node, p: *Parser) !?Diagnostics.Message {
pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Parser.Result, node: Tree.Node, p: *Parser) !?Diagnostics.Message {
switch (attr) {
inline else => |tag| {
const decl = @typeInfo(attributes).Struct.decls[@intFromEnum(tag)];
Expand All @@ -312,7 +312,7 @@ pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, val: Value, node
const arg_fields = std.meta.fields(@field(attributes, decl.name));
switch (arg_idx) {
inline 0...arg_fields.len - 1 => |arg_i| {
return diagnoseField(decl, arg_fields[arg_i], UnwrapOptional(arg_fields[arg_i].type), arguments, val, node, p);
return diagnoseField(decl, arg_fields[arg_i], UnwrapOptional(arg_fields[arg_i].type), arguments, res, node, p);
},
else => unreachable,
}
Expand Down
13 changes: 12 additions & 1 deletion src/Ir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,18 @@ fn writeType(ir: Ir, ty_ref: Interner.Ref, color: bool, w: anytype) !void {
fn writeValue(ir: Ir, val_ref: Interner.Ref, color: bool, w: anytype) !void {
const v: Value = .{ .opt_ref = @enumFromInt(@intFromEnum(val_ref)) };
if (color) util.setColor(LITERAL, w);
try v.print(ir.interner, w);
const key = ir.interner.get(v.ref());
switch (key) {
.null => return w.writeAll("nullptr_t"),
.int => |repr| switch (repr) {
inline else => |x| return w.print("{d}", .{x}),
},
.float => |repr| switch (repr) {
inline else => |x| return w.print("{d}", .{@as(f64, @floatCast(x))}),
},
.bytes => |b| return std.zig.fmt.stringEscape(b, "", .{}, w),
else => unreachable, // not a value
}
}

fn writeRef(ir: Ir, ref_map: *RefMap, ref: Ref, color: bool, w: anytype) !void {
Expand Down
63 changes: 30 additions & 33 deletions src/Parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ fn expectClosing(p: *Parser, opening: TokenIndex, id: Token.Id) Error!void {
}

fn errOverflow(p: *Parser, op_tok: TokenIndex, res: Result) !void {
try p.errStr(.overflow, op_tok, try p.valStr(res.val));
try p.errStr(.overflow, op_tok, try res.str(p));
}

fn errExpectedToken(p: *Parser, expected: Token.Id, actual: Token.Id) Error {
Expand Down Expand Up @@ -414,21 +414,6 @@ pub fn removeNull(p: *Parser, str: Value) !Value {
return Value.intern(p.comp, .{ .bytes = p.strings.items[strings_top..] });
}

pub fn valStr(p: *Parser, val: Value) ![]const u8 {
switch (val.opt_ref) {
.none => return "(none)",
.zero => return "0",
.one => return "1",
.null => return "nullptr_t",
else => {},
}
const strings_top = p.strings.items.len;
defer p.strings.items.len = strings_top;

try val.print(&p.comp.interner, p.strings.writer());
return try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
}

pub fn typeStr(p: *Parser, ty: Type) ![]const u8 {
if (Type.Builder.fromType(ty).str(p.comp.langopts)) |str| return str;
const strings_top = p.strings.items.len;
Expand Down Expand Up @@ -469,9 +454,9 @@ pub fn floatValueChangedStr(p: *Parser, res: *Result, old_value: Value, int_ty:
try w.writeAll(" changes ");
if (res.val.isZero(p.comp)) try w.writeAll("non-zero ");
try w.writeAll("value from ");
try old_value.print(&p.comp.interner, w);
try old_value.print(res.ty, p.comp, w);
try w.writeAll(" to ");
try res.val.print(&p.comp.interner, w);
try res.val.print(int_ty, p.comp, w);

return try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
}
Expand Down Expand Up @@ -1198,8 +1183,7 @@ fn staticAssertMessage(p: *Parser, cond_node: NodeIndex, message: Result) !?[]co
}
const bytes = p.comp.interner.get(message.val.ref()).bytes;
try buf.ensureUnusedCapacity(bytes.len);
const size: Compilation.CharUnitSize = @enumFromInt(message.ty.elemType().sizeof(p.comp).?);
try Value.printString(bytes, size, buf.writer());
try Value.printString(bytes, message.ty, p.comp, buf.writer());
}
return try p.comp.diag.arena.allocator().dupe(u8, buf.items);
}
Expand Down Expand Up @@ -1612,10 +1596,10 @@ fn attribute(p: *Parser, kind: Attribute.Kind, namespace: ?[]const u8) Error!?Te

fn diagnose(p: *Parser, attr: Attribute.Tag, arguments: *Attribute.Arguments, arg_idx: u32, res: Result) !?Diagnostics.Message {
if (Attribute.wantsAlignment(attr, arg_idx)) {
return Attribute.diagnoseAlignment(attr, arguments, arg_idx, res.val, p);
return Attribute.diagnoseAlignment(attr, arguments, arg_idx, res, p);
}
const node = p.nodes.get(@intFromEnum(res.node));
return Attribute.diagnose(attr, arguments, arg_idx, res.val, node, p);
return Attribute.diagnose(attr, arguments, arg_idx, res, node, p);
}

/// attributeList : (attribute (',' attribute)*)?
Expand Down Expand Up @@ -2276,7 +2260,7 @@ fn recordDeclarator(p: *Parser) Error!bool {
try p.errTok(.expected_integer_constant_expr, bits_tok);
break :bits;
} else if (res.val.compare(.lt, Value.zero, p.comp)) {
try p.errStr(.negative_bitwidth, first_tok, try p.valStr(res.val));
try p.errStr(.negative_bitwidth, first_tok, try res.str(p));
break :bits;
}

Expand Down Expand Up @@ -2736,13 +2720,13 @@ fn enumerator(p: *Parser, e: *Enumerator) Error!?EnumFieldAndNode {
const min_int = (Type{ .specifier = .int }).minInt(p.comp);
const min_val = try Value.int(min_int, p.comp);
if (e.res.val.compare(.lt, min_val, p.comp)) {
try p.errStr(.enumerator_too_small, name_tok, try p.valStr(e.res.val));
try p.errStr(.enumerator_too_small, name_tok, try e.res.str(p));
}
} else {
const max_int = (Type{ .specifier = .int }).maxInt(p.comp);
const max_val = try Value.int(max_int, p.comp);
if (e.res.val.compare(.gt, max_val, p.comp)) {
try p.errStr(.enumerator_too_large, name_tok, try p.valStr(e.res.val));
try p.errStr(.enumerator_too_large, name_tok, try e.res.str(p));
}
}
}
Expand Down Expand Up @@ -3264,14 +3248,14 @@ fn initializerItem(p: *Parser, il: *InitList, init_ty: Type) Error!bool {
try p.errTok(.expected_integer_constant_expr, expr_tok);
return error.ParsingFailed;
} else if (index_res.val.compare(.lt, Value.zero, p.comp)) {
try p.errStr(.negative_array_designator, l_bracket + 1, try p.valStr(index_res.val));
try p.errStr(.negative_array_designator, l_bracket + 1, try index_res.str(p));
return error.ParsingFailed;
}

const max_len = cur_ty.arrayLen() orelse std.math.maxInt(usize);
const index_int = index_res.val.toInt(u64, p.comp) orelse std.math.maxInt(u64);
if (index_int >= max_len) {
try p.errStr(.oob_array_designator, l_bracket + 1, try p.valStr(index_res.val));
try p.errStr(.oob_array_designator, l_bracket + 1, try index_res.str(p));
return error.ParsingFailed;
}
cur_index_hint = cur_index_hint orelse index_int;
Expand Down Expand Up @@ -4371,7 +4355,7 @@ fn labeledStmt(p: *Parser) Error!?NodeIndex {
const prev = (try some.add(first, last, case + 1)) orelse break :check;

// TODO check which value was already handled
try p.errStr(.duplicate_switch_case, case + 1, try p.valStr(first));
try p.errStr(.duplicate_switch_case, case + 1, try first_item.str(p));
try p.errTok(.previous_case, prev.tok);
} else {
try p.errStr(.case_not_in_switch, case, "case");
Expand Down Expand Up @@ -4811,11 +4795,24 @@ const CallExpr = union(enum) {
}
};

const Result = struct {
pub const Result = struct {
node: NodeIndex = .none,
ty: Type = .{ .specifier = .int },
val: Value = .{},

pub fn str(res: Result, p: *Parser) ![]const u8 {
switch (res.val.opt_ref) {
.none => return "(none)",
.null => return "nullptr_t",
else => {},
}
const strings_top = p.strings.items.len;
defer p.strings.items.len = strings_top;

try res.val.print(res.ty, p.comp, p.strings.writer());
return try p.comp.diag.arena.allocator().dupe(u8, p.strings.items[strings_top..]);
}

fn expect(res: Result, p: *Parser) Error!void {
if (p.in_macro) {
if (res.val.opt_ref == .none) {
Expand Down Expand Up @@ -7327,7 +7324,7 @@ fn checkArrayBounds(p: *Parser, index: Result, array: Result, tok: TokenIndex) !
const record = lhs.getRecord().?;
if (data.member.index + 1 == record.fields.len) {
if (!index.val.isZero(p.comp)) {
try p.errStr(.old_style_flexible_struct, tok, try p.valStr(index.val));
try p.errStr(.old_style_flexible_struct, tok, try index.str(p));
}
return;
}
Expand All @@ -7337,13 +7334,13 @@ fn checkArrayBounds(p: *Parser, index: Result, array: Result, tok: TokenIndex) !
const index_int = index.val.toInt(u64, p.comp) orelse std.math.maxInt(u64);
if (index.ty.isUnsignedInt(p.comp)) {
if (index_int >= array_len) {
try p.errStr(.array_after, tok, try p.valStr(index.val));
try p.errStr(.array_after, tok, try index.str(p));
}
} else {
if (index.val.compare(.lt, Value.zero, p.comp)) {
try p.errStr(.array_before, tok, try p.valStr(index.val));
try p.errStr(.array_before, tok, try index.str(p));
} else if (index_int >= array_len) {
try p.errStr(.array_after, tok, try p.valStr(index.val));
try p.errStr(.array_after, tok, try index.str(p));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Tree.zig
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,7 @@ fn dumpNode(tree: *const Tree, node: NodeIndex, level: u32, mapper: StringIntern
if (tree.value_map.get(node)) |val| {
if (color) util.setColor(LITERAL, w);
try w.writeAll(" (value: ");
try val.print(&tree.comp.interner, w);
try val.print(ty, tree.comp, w);
try w.writeByte(')');
}
if (tag == .implicit_return and data.return_zero) {
Expand Down
12 changes: 8 additions & 4 deletions src/Value.zig
Original file line number Diff line number Diff line change
Expand Up @@ -677,8 +677,11 @@ pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, comp: *cons
return lhs_bigint.order(rhs_bigint).compare(op);
}

pub fn print(v: Value, interner: *const Interner, w: anytype) @TypeOf(w).Error!void {
const key = interner.get(v.ref());
pub fn print(v: Value, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w).Error!void {
if (ty.is(.bool)) {
return w.writeAll(if (v.isZero(comp)) "false" else "true");
}
const key = comp.interner.get(v.ref());
switch (key) {
.null => return w.writeAll("nullptr_t"),
.int => |repr| switch (repr) {
Expand All @@ -687,12 +690,13 @@ pub fn print(v: Value, interner: *const Interner, w: anytype) @TypeOf(w).Error!v
.float => |repr| switch (repr) {
inline else => |x| return w.print("{d}", .{@as(f64, @floatCast(x))}),
},
.bytes => |b| return printString(b, .@"1", w),
.bytes => |b| return printString(b, ty, comp, w),
else => unreachable, // not a value
}
}

pub fn printString(bytes: []const u8, size: Compilation.CharUnitSize, w: anytype) @TypeOf(w).Error!void {
pub fn printString(bytes: []const u8, ty: Type, comp: *const Compilation, w: anytype) @TypeOf(w).Error!void {
const size: Compilation.CharUnitSize = @enumFromInt(ty.elemType().sizeof(comp).?);
const without_null = bytes[0 .. bytes.len - @intFromEnum(size)];
switch (size) {
inline .@"1", .@"2" => |sz| {
Expand Down

0 comments on commit e789edd

Please sign in to comment.