Pass the sanity test
This commit is contained in:
parent
aec8f51451
commit
75fc1506e5
5 changed files with 101 additions and 10 deletions
|
@ -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" {
|
||||
|
|
|
@ -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)] = ' ';
|
||||
|
|
36
src/interpreter.zig
Normal file
36
src/interpreter.zig
Normal file
|
@ -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());
|
||||
}
|
49
src/main.zig
49
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);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Add table
Reference in a new issue