feat: folding logical operations

This commit is contained in:
Brett Broadhurst 2026-03-29 04:49:03 -06:00
parent 92e8bcd866
commit 2260ccda25
Failed to generate hash of commit
24 changed files with 310 additions and 151 deletions

View file

@ -46,6 +46,15 @@ pub const Value = union(enum) {
return v == .int or v == .float;
}
pub fn coerce(v: Value) ?Value {
return switch (v) {
.int => v,
.float => v,
.bool => |boolean| .{ .int = if (boolean) 1 else 0 },
else => null,
};
}
pub fn isTruthy(v: Value) bool {
return switch (v) {
//.nil => false,
@ -69,8 +78,11 @@ pub const Value = union(enum) {
}
pub fn arith(lhs: Value, rhs: Value, op: Opcode, story: *Story) !Value {
if (lhs.isNumeric() and rhs.isNumeric())
return numericArith(lhs, rhs, op);
if (lhs.coerce()) |l| {
if (rhs.coerce()) |r| {
return numericArith(l, r, op);
}
}
if (op == .add) {
if (lhs == .object and lhs.object.tag == .string)
return concat(lhs, rhs, story);
@ -177,6 +189,36 @@ pub const Value = union(enum) {
.object => return error.TypeError,
}
}
pub fn format(value: Value, writer: *std.Io.Writer) error{WriteFailed}!void {
switch (value) {
.bool => |boolean| try writer.writeAll(if (boolean) "true" else "false"),
.int => |int| try writer.print("{d}", .{int}),
.float => |float| {
var buf: [64]u8 = undefined;
if (std.math.isNan(float)) return writer.writeAll("NaN");
if (std.math.isInf(float)) return writer.writeAll(if (float > 0) "Inf" else "-Inf");
var str = std.fmt.bufPrint(&buf, "{d:.7}", .{float}) catch |err| switch (err) {
error.NoSpaceLeft => unreachable,
else => |e| return e,
};
if (std.mem.indexOfScalar(u8, str, '.')) |dot| {
var end = str.len;
while (end > dot + 2 and str[end - 1] == '0') end -= 1;
str = str[0..end];
}
try writer.writeAll(str);
},
.object => |object| switch (object.tag) {
.string => {
const typed: *const Object.String = @ptrCast(object);
try writer.writeAll(typed.toSlice());
},
else => try writer.print("<{s} {*}>", .{ object.tag.tagBytes(), object }),
},
}
}
};
pub const CallFrame = struct {