level 1 compilation woo!

i'm sure 1 test will be enough what could go wrong hahahaha
This commit is contained in:
mehbark 2024-06-24 21:25:17 -04:00
parent 1da2ac74d4
commit 7301699729

159
bf.zig
View file

@ -2,7 +2,150 @@
const std = @import("std"); const std = @import("std");
const io = std.io; const io = std.io;
const fs = std.fs; const fs = std.fs;
const mem = std.mem;
const process = std.process; 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 { pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); 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); var memory = try allocator.alloc(u8, 1 << 16);
for (mem) |*m| { for (memory) |*m| {
m.* = 0; m.* = 0;
} }
var mp: u16 = 0; var mp: u16 = 0;
@ -41,12 +184,12 @@ pub fn main() !void {
while (ip < prog_len) { while (ip < prog_len) {
switch (prog[ip]) { switch (prog[ip]) {
'+' => mem[mp] +%= 1, '+' => memory[mp] +%= 1,
'-' => mem[mp] -%= 1, '-' => memory[mp] -%= 1,
'>' => mp +%= 1, '>' => mp +%= 1,
'<' => mp -%= 1, '<' => mp -%= 1,
'[' => { '[' => {
if (mem[mp] == 0) { if (memory[mp] == 0) {
var depth: i16 = 1; var depth: i16 = 1;
ip += 1; ip += 1;
while (depth > 0) : (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; var depth: i16 = 1;
ip -= 1; ip -= 1;
while (depth > 0) : (ip -= 1) { while (depth > 0) : (ip -= 1) {
@ -73,8 +216,8 @@ pub fn main() !void {
ip += 1; ip += 1;
} }
}, },
'.' => try out.writeByte(mem[mp]), ',' => memory[mp] = in.readByte() catch 0,
',' => mem[mp] = in.readByte() catch 0, '.' => try out.writeByte(memory[mp]),
else => unreachable, else => unreachable,
} }
ip += 1; ip += 1;