feat: cheaper runtime value type, float and int arithmetic rules

This commit is contained in:
Brett Broadhurst 2026-03-29 02:24:02 -06:00
parent 9b5cd4038f
commit 92e8bcd866
Failed to generate hash of commit
13 changed files with 630 additions and 448 deletions

View file

@ -303,12 +303,18 @@ const GenIr = struct {
return new_index;
}
fn addInt(gi: *GenIr, value: u64) !Ir.Inst.Ref {
fn addInt(gi: *GenIr, value: i64) !Ir.Inst.Ref {
return add(gi, .{ .tag = .int, .data = .{
.int = value,
} });
}
fn addFloat(gi: *GenIr, value: f64) !Ir.Inst.Ref {
return add(gi, .{ .tag = .float, .data = .{
.float = value,
} });
}
fn addUnaryNode(gi: *GenIr, tag: Ir.Inst.Tag, arg: Ir.Inst.Ref) !Ir.Inst.Ref {
return add(gi, .{ .tag = tag, .data = .{
.un = .{ .lhs = arg },
@ -531,10 +537,7 @@ fn setDeclVarPayload(
astgen.appendBlockBody(body);
}
fn setDeclStitchPayload(
decl_index: Ir.Inst.Index,
body_block: *GenIr,
) !void {
fn setDeclStitchPayload(decl_index: Ir.Inst.Index, body_block: *GenIr) !void {
defer body_block.unstack();
const astgen = body_block.astgen;
@ -659,10 +662,51 @@ fn logicalOp(
gen.setLabel(else_label);
}
fn parseNumberLiteral(bytes: []const u8) union(enum) {
int: i64,
float: f64,
failure: union(enum) {
duplicate_period: usize,
invalid_character: usize,
},
} {
var is_float = false;
var period = false;
for (bytes, 0..) |c, i| {
switch (c) {
'.' => {
if (period) return .{ .failure = .{ .duplicate_period = i } };
period = true;
is_float = true;
},
'0'...'9' => {},
else => return .{ .failure = .{ .invalid_character = i } },
}
}
if (is_float) {
const value = std.fmt.parseFloat(f64, bytes) catch |err| switch (err) {
error.InvalidCharacter => unreachable,
};
return .{ .float = value };
} else {
const value = std.fmt.parseInt(i64, bytes, 10) catch |err| switch (err) {
error.InvalidCharacter => unreachable,
error.Overflow => unreachable,
};
return .{ .int = value };
}
}
fn numberLiteral(block: *GenIr, node: *const Ast.Node) InnerError!Ir.Inst.Ref {
const lexeme = block.astgen.tree.nodeSlice(node);
const int_value = try std.fmt.parseUnsigned(u64, lexeme, 10);
return block.addInt(int_value);
const astgen = block.astgen;
const lexeme = astgen.tree.nodeSlice(node);
switch (parseNumberLiteral(lexeme)) {
.int => |int| return block.addInt(int),
.float => |float| return block.addFloat(float),
// TODO: exact offset reporting
.failure => return fail(block.astgen, node, "invalid number literal", .{}),
}
}
fn stringLiteral(gi: *GenIr, node: *const Ast.Node) InnerError!Ir.Inst.Ref {