feature. See also
. The project being documented here (as the example) is the Zig library itself.
ZonGen.numberLiteral
fn numberLiteral(zg: *ZonGen, num_node: Ast.Node.Index, src_node: Ast.Node.Index, dest_node: Zoir.Node.Index, sign: enum
File
Code
fn numberLiteral(zg: *ZonGen, num_node: Ast.Node.Index, src_node: Ast.Node.Index, dest_node: Zoir.Node.Index, sign: enum { negative, positive }) !void {
const tree = zg.tree;
const num_token = tree.nodeMainToken(num_node);
const num_bytes = tree.tokenSlice(num_token);
switch (std.zig.parseNumberLiteral(num_bytes)) {
.int => |unsigned_num| {
if (unsigned_num == 0 and sign == .negative) {
try zg.addErrorTokNotes(num_token, "integer literal '-0' is ambiguous", .{}, &.{
try zg.errNoteTok(num_token, "use '0' for an integer zero", .{}),
try zg.errNoteTok(num_token, "use '-0.0' for a floating-point signed zero", .{}),
});
return;
}
const num: i65 = switch (sign) {
.positive => unsigned_num,
.negative => -@as(i65, unsigned_num),
};
if (std.math.cast(i32, num)) |x| {
zg.setNode(dest_node, .{
.tag = .int_literal_small,
.data = @bitCast(x),
.ast_node = src_node,
});
return;
}
const max_limbs = comptime std.math.big.int.calcTwosCompLimbCount(@bitSizeOf(@TypeOf(num)));
var limbs: [max_limbs]std.math.big.Limb = undefined;
var big_int: std.math.big.int.Mutable = .init(&limbs, num);
try zg.setBigIntLiteralNode(dest_node, src_node, big_int.toConst());
},
.big_int => |base| {
const gpa = zg.gpa;
const num_without_prefix = switch (base) {
.decimal => num_bytes,
.hex, .binary, .octal => num_bytes[2..],
};
var big_int: std.math.big.int.Managed = try .init(gpa);
defer big_int.deinit();
big_int.setString(@backingInt(base), num_without_prefix) catch |err| switch (err) {
error.InvalidCharacter => unreachable,
error.InvalidBase => unreachable,
error.OutOfMemory => |e| return e,
};
switch (sign) {
.positive => {},
.negative => big_int.negate(),
}
try zg.setBigIntLiteralNode(dest_node, src_node, big_int.toConst());
},
.float => {
const unsigned_num = std.fmt.parseFloat(f128, num_bytes) catch |err| switch (err) {
error.InvalidCharacter => unreachable,
};
const num: f128 = switch (sign) {
.positive => unsigned_num,
.negative => -unsigned_num,
};
{
@setFloatMode(.strict);
const smaller_float: f32 = @floatCast(num);
const bigger_again: f128 = smaller_float;
if (bigger_again == num) {
zg.setNode(dest_node, .{
.tag = .float_literal_small,
.data = @bitCast(smaller_float),
.ast_node = src_node,
});
return;
}
}
const elems: [4]u32 = @bitCast(num);
const extra_index: u32 = @intCast(zg.extra.items.len);
try zg.extra.appendSlice(zg.gpa, &elems);
zg.setNode(dest_node, .{
.tag = .float_literal,
.data = extra_index,
.ast_node = src_node,
});
},
.failure => |err| try zg.lowerNumberError(err, num_token, num_bytes),
}
}