From 75fc1506e59c1eaa52971d20df72c7cbeca5ac82 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Thu, 9 Jun 2022 23:17:53 +0200 Subject: Pass the sanity test --- src/defaultIO.zig | 10 ++++------ src/field.zig | 2 +- src/interpreter.zig | 36 ++++++++++++++++++++++++++++++++++++ src/main.zig | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/pointer.zig | 14 +++++++++++--- 5 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 src/interpreter.zig diff --git a/src/defaultIO.zig b/src/defaultIO.zig index b87c2d6..9da4ad2 100644 --- a/src/defaultIO.zig +++ b/src/defaultIO.zig @@ -16,15 +16,13 @@ pub fn decimalInput() IOErrors!i64 { } pub fn characterOutput(v: i64) IOErrors!void { - // TODO - _ = v; - return error.NotImplemented; + std.debug.print("{c}", .{@intCast(u8, v)}); + return; } pub fn decimalOutput(v: i64) IOErrors!void { - // TODO - _ = v; - return error.NotImplemented; + std.debug.print("{d}", .{v}); + return; } test "all" { diff --git a/src/field.zig b/src/field.zig index c0a0b52..1e9b56f 100644 --- a/src/field.zig +++ b/src/field.zig @@ -6,7 +6,7 @@ const Line = struct { data: std.ArrayList(i64), fn blank(l: *Line, x: i64) void { const lx = @intCast(i64, l.len()); - if (x < l.x or x > l.x + lx) { // outside the field + if (x < l.x or x > l.x + lx - 1) { // outside the field return; } else if (x > l.x and x < l.x + lx - 1) { // just set the value l.data.items[@intCast(usize, x - l.x)] = ' '; diff --git a/src/interpreter.zig b/src/interpreter.zig new file mode 100644 index 0000000..5702336 --- /dev/null +++ b/src/interpreter.zig @@ -0,0 +1,36 @@ +const std = @import("std"); +const field = @import("field.zig"); +const pointer = @import("pointer.zig"); + +pub const Interpreter = struct { + allocator: std.mem.Allocator, + field: *field.Field, + pointer: *pointer.Pointer, + + pub fn deinit(self: *Interpreter) void { + self.allocator.destroy(self); + } + pub fn init(allocator: std.mem.Allocator, f: *field.Field, p: *pointer.Pointer) !*Interpreter { + var i = try allocator.create(Interpreter); + errdefer allocator.destroy(i); + i.allocator = allocator; + i.field = f; + i.pointer = p; + return i; + } + pub fn run(self: *Interpreter) !i64 { + while (true) { + if (try self.pointer.exec()) |ret| { + if (ret.code) |code| { + return code; + } else { + return 0; + } + } + } + } +}; + +test "all" { + std.testing.refAllDecls(@This()); +} diff --git a/src/main.zig b/src/main.zig index 14bada3..7460c60 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,5 +1,6 @@ const std = @import("std"); const field = @import("field.zig"); +const interpreter = @import("interpreter.zig"); const pointer = @import("pointer.zig"); const stackStack = @import("stackStack.zig"); @@ -10,3 +11,51 @@ pub fn main() anyerror!void { test "all" { std.testing.refAllDecls(@This()); } +test "minimal" { + const minimal = std.io.fixedBufferStream("@").reader(); + var f = try field.Field.init(std.testing.allocator); + defer f.deinit(); + try f.load(minimal); + const argv = [_][]const u8{"minimal"}; + var p = try pointer.Pointer.init(std.testing.allocator, f, null, argv[0..]); + defer p.deinit(); + + var i = try interpreter.Interpreter.init(std.testing.allocator, f, p); + defer i.deinit(); + + var code = try i.run(); + try std.testing.expectEqual(code, 0); +} +test "almost minimal" { + const minimal = std.io.fixedBufferStream(" @").reader(); + var f = try field.Field.init(std.testing.allocator); + defer f.deinit(); + try f.load(minimal); + const argv = [_][]const u8{"minimal"}; + var p = try pointer.Pointer.init(std.testing.allocator, f, null, argv[0..]); + defer p.deinit(); + + var i = try interpreter.Interpreter.init(std.testing.allocator, f, p); + defer i.deinit(); + + var code = try i.run(); + try std.testing.expectEqual(code, 0); +} +test "sanity" { + var file = try std.fs.cwd().openFile("mycology/sanity.bf", .{}); + defer file.close(); + + var f = try field.Field.init(std.testing.allocator); + defer f.deinit(); + try f.load(file.reader()); + + const argv = [_][]const u8{"sanity"}; + var p = try pointer.Pointer.init(std.testing.allocator, f, null, argv[0..]); + defer p.deinit(); + + var i = try interpreter.Interpreter.init(std.testing.allocator, f, p); + defer i.deinit(); + + var code = try i.run(); + try std.testing.expectEqual(code, 0); +} diff --git a/src/pointer.zig b/src/pointer.zig index dcbca46..485a485 100644 --- a/src/pointer.zig +++ b/src/pointer.zig @@ -203,11 +203,19 @@ pub const Pointer = struct { 'o' => return error.NotImplemented, '=' => return error.NotImplemented, 't' => return error.NotImplemented, - else => return error.NotImplemented, + else => if (!p.redirect(c)) { + if (c >= '0' and c <= '9') { + try p.ss.toss.push(c - '0'); + } else if (c >= 'a' and c <= 'f') { + try p.ss.toss.push(c - 'a' + 10); + } else { + p.reverse(); + } + }, } return null; } - fn exec(self: *Pointer) !?pointerReturn { + pub fn exec(self: *Pointer) !?pointerReturn { // Advances to the next instruction of the field and executes it // Returns non nil if the pointer terminated, and a return code if // the program should terminate completely @@ -279,7 +287,7 @@ pub const Pointer = struct { p.dy = 0; }, '?' => { - const directions = []i8{ 0, -1, 1, 0, 0, 1, -1, 0 }; + const directions = [_]i8{ 0, -1, 1, 0, 0, 1, -1, 0 }; const r = 2 * p.rand.intRangeAtMost(u8, 0, 3); p.dx = directions[r]; p.dy = directions[r + 1]; -- cgit v1.2.3