From 73016997295a9687c2de8d11069ad6f491fbe99f Mon Sep 17 00:00:00 2001 From: mehbark Date: Mon, 24 Jun 2024 21:25:17 -0400 Subject: [PATCH] level 1 compilation woo! i'm sure 1 test will be enough what could go wrong hahahaha --- bf.zig | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 151 insertions(+), 8 deletions(-) diff --git a/bf.zig b/bf.zig index 99aad46..df07f07 100644 --- a/bf.zig +++ b/bf.zig @@ -2,7 +2,150 @@ const std = @import("std"); const io = std.io; const fs = std.fs; +const mem = std.mem; const process = std.process; +const testing = std.testing; +const ArrayList = std.ArrayList; + +const Level1 = union(enum) { + // think about it... i hope + inc: i16, + shift: i16, + // u8 because why would we be reading to/writing from the same cell 256 times in a row + // well, might as well use the extra space (union is bigger than its biggest member) + in: u16, + out: u16, + loop_start, + loop_end, + + const Self = @This(); + fn pointless(self: Self) bool { + return switch (self) { + .inc, .shift => |n| n == 0, + .in, .out => |n| n == 0, + else => false, + }; + } +}; + +const Level2 = union(enum) { + inc: i16, + shift: i16, + in: u16, + out: u16, + // only difference + // u24s because i arbitrarily chose 2^24 as the limit + // maybe u32 would be more efficient idk this union should fit in a u32 + // hm we can probably go way lower bc level1 is so much more compact than prog_unfiltered + // shouldn't be necessary + loop_start: u24, + loop_end: u24, +}; + +// we'll do the discarding of comment chars here +fn compileLevel1(allocator: mem.Allocator, src: []const u8) !ArrayList(Level1) { + var cur: ?Level1 = null; + var out = ArrayList(Level1).init(allocator); + + for (src) |b| { + switch (b) { + '+', '-' => { + const n: i16 = if (b == '+') 1 else -1; + if (cur) |*ins| { + switch (ins.*) { + .inc => |*ns| ns.* += n, + else => { + if (!ins.pointless()) try out.append(ins.*); + cur = .{ .inc = n }; + }, + } + } else { + cur = .{ .inc = n }; + } + }, + '>', '<' => { + const n: i16 = if (b == '>') 1 else -1; + if (cur) |*ins| { + switch (ins.*) { + .shift => |*ns| ns.* += n, + else => { + if (!ins.pointless()) try out.append(ins.*); + cur = .{ .shift = n }; + }, + } + } else { + cur = .{ .shift = n }; + } + }, + '[', ']' => { + if (cur) |ins| { + if (!ins.pointless()) try out.append(ins); + cur = null; + } + try out.append(if (b == '[') .loop_start else .loop_end); + }, + ',' => { + if (cur) |*ins| { + switch (ins.*) { + .in => |*ns| ns.* += 1, + else => { + if (!ins.pointless()) try out.append(ins.*); + cur = .{ .in = 1 }; + }, + } + } else { + cur = .{ .in = 1 }; + } + }, + '.' => { + if (cur) |*ins| { + switch (ins.*) { + .out => |*ns| ns.* += 1, + else => { + if (!ins.pointless()) try out.append(ins.*); + cur = .{ .out = 1 }; + }, + } + } else { + cur = .{ .out = 1 }; + } + }, + else => {}, + } + } + + if (cur) |ins| { + if (!ins.pointless()) try out.append(ins); + } + + return out; +} + +test "level 1" { + const src = "+++-- [ >><<< +- ] ...,,,"; + + const level1 = try compileLevel1(testing.allocator, src); + defer level1.deinit(); + + std.debug.print("{any}\n", .{level1.items}); + + const should_be = [_]Level1{ + .{ .inc = 1 }, + .loop_start, + .{ .shift = -1 }, + .loop_end, + .{ .out = 3 }, + .{ .in = 3 }, + }; + try testing.expectEqual(should_be.len, level1.items.len); + + for ( + level1.items, + &should_be, + ) |a, b| { + try testing.expectEqual(a, b); + } +} pub fn main() !void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); @@ -32,8 +175,8 @@ pub fn main() !void { } } - var mem = try allocator.alloc(u8, 1 << 16); - for (mem) |*m| { + var memory = try allocator.alloc(u8, 1 << 16); + for (memory) |*m| { m.* = 0; } var mp: u16 = 0; @@ -41,12 +184,12 @@ pub fn main() !void { while (ip < prog_len) { switch (prog[ip]) { - '+' => mem[mp] +%= 1, - '-' => mem[mp] -%= 1, + '+' => memory[mp] +%= 1, + '-' => memory[mp] -%= 1, '>' => mp +%= 1, '<' => mp -%= 1, '[' => { - if (mem[mp] == 0) { + if (memory[mp] == 0) { var depth: i16 = 1; ip += 1; while (depth > 0) : (ip += 1) { @@ -60,7 +203,7 @@ pub fn main() !void { } }, ']' => { - if (mem[mp] != 0) { + if (memory[mp] != 0) { var depth: i16 = 1; ip -= 1; while (depth > 0) : (ip -= 1) { @@ -73,8 +216,8 @@ pub fn main() !void { ip += 1; } }, - '.' => try out.writeByte(mem[mp]), - ',' => mem[mp] = in.readByte() catch 0, + ',' => memory[mp] = in.readByte() catch 0, + '.' => try out.writeByte(memory[mp]), else => unreachable, } ip += 1;