const std = @import("std");
const Term = union(enum) {
variable: []const u8,
abstraction: Abstraction,
application: Application,
pub const Abstraction = struct {
parameter: []const u8,
body: *Term,
pub fn format(
self: Abstraction,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
try writer.print("\\{s} -> {}\n", .{ self.parameter, self.body });
}
};
pub const Application = struct {
function: *Term,
argument: *Term,
pub fn format(
self: Application,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
try writer.print("({} {})\n", .{ self.function, self.argument });
}
};
pub fn init_variable(name: []const u8) Term {
return .{ .variable = name };
}
pub fn init_abstraction(name: []const u8, body: *Term) Term {
return .{ .abstraction = .{ .parameter = name, .body = body } };
}
pub fn init_application(function: *const Term, argument: *Term) Term {
return .{ .application = .{ .function = function, .argument = argument } };
}
pub fn format(
self: Term,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
switch (self) {
.variable => try writer.print("{s}", .{self.variable}),
.abstraction => try writer.print("{s}", .{self.abstraction}),
.application => try writer.print("{s}", .{self.application}),
}
}
};
pub fn main() !void {
const identity = Term.init_abstraction("x", &Term.init_variable("x"));
std.debug.print("{}\n", .{identity});
}
#Code review and cast discards const qualifier fix
1 messages · Page 1 of 1 (latest)
I'm writing a little lambda calc interpreter and would like a code review to see whether I'm on the right path
Also, I'm not entirely sure how to get rid of the "cast discards const qualifier" error I'm getting in my main function
you need to put the result of init_variable into a var, right now its a temporary which when you take the address of it its a const
you could alternatively use *const Term instead which would allow you to use temporaries, but only if you dont need to mutate
there isnt much so i couldnt really say whether you need all these pointers since i havent made something like this before.
i usually only see init functions if its doing something other than just assigning fields, otherwise just use the normal initialization syntax. although i agree unions can be noisy.
i guess the functions dont follow naming conventions but thats not really important
i guess the only advice i could give is consider using indexes into a list instead of pointers but its so early on that doing whatever is most obvious is best imo
to avoid memory fragmentation?
yeah, im assuming youre going to have to heap allocate these once it gets more complicated