aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/defaultIO.zig10
-rw-r--r--src/field.zig2
-rw-r--r--src/interpreter.zig36
-rw-r--r--src/main.zig49
-rw-r--r--src/pointer.zig14
5 files changed, 101 insertions, 10 deletions
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];