diff options
-rw-r--r-- | src/field.zig | 46 | ||||
-rw-r--r-- | src/pointer.zig | 32 |
2 files changed, 48 insertions, 30 deletions
diff --git a/src/field.zig b/src/field.zig index 0130848..02bf544 100644 --- a/src/field.zig +++ b/src/field.zig @@ -393,35 +393,49 @@ pub const Field = struct { try std.testing.expectEqual(f.get(8, 2), '2'); try std.testing.expectEqual(f.get(9, 2), ' '); } - pub fn step(f: *Field, x: i64, y: i64, dx: i64, dy: i64) struct { x: i64, y: i64 } { + pub fn step(f: *Field, x: i64, y: i64, dx: i64, dy: i64, smartAdvance: bool, jumping: bool) struct { x: i64, y: i64 } { var a = x + dx; var b = y + dy; - if (f.isIn(a, b)) return .{ .x = a, .y = b }; - // # We are stepping outside, we need to wrap the Lahey-space - a = x; - b = y; - while (true) { - var c = a - dx; - var d = b - dy; - if (!f.isIn(c, d)) return .{ .x = a, .y = b }; - a = c; - b = d; + if (!f.isIn(a, b)) { + // # We are stepping outside, we need to wrap the Lahey-space + a = x; + b = y; + while (true) { + var c = a - dx; + var d = b - dy; + if (!f.isIn(c, d)) break; + a = c; + b = d; + } + } + if (smartAdvance) { + const v = f.get(a, b); + if (jumping) { + return f.step(a, b, dx, dy, true, v != ';'); + } + if (v == ' ') { + return f.step(a, b, dx, dy, true, false); + } + if (v == ';') { + return f.step(a, b, dx, dy, true, true); + } } + return .{ .x = a, .y = b }; } test "step" { var minimal = std.io.fixedBufferStream("@"); var f = try Field.init(std.testing.allocator); defer f.deinit(); try f.load(minimal.reader()); - try std.testing.expectEqual(f.step(0, 0, 0, 0), .{ .x = 0, .y = 0 }); - try std.testing.expectEqual(f.step(0, 0, 1, 0), .{ .x = 0, .y = 0 }); + try std.testing.expectEqual(f.step(0, 0, 0, 0, false, false), .{ .x = 0, .y = 0 }); + try std.testing.expectEqual(f.step(0, 0, 1, 0, false, false), .{ .x = 0, .y = 0 }); var hello = std.io.fixedBufferStream("64+\"!dlroW ,olleH\">:#,_@\n"); var fHello = try Field.init(std.testing.allocator); defer fHello.deinit(); try fHello.load(hello.reader()); - try std.testing.expectEqual(fHello.step(3, 0, 0, 0), .{ .x = 3, .y = 0 }); - try std.testing.expectEqual(fHello.step(3, 0, 1, 0), .{ .x = 4, .y = 0 }); - try std.testing.expectEqual(fHello.step(0, 0, -1, 0), .{ .x = 23, .y = 0 }); + try std.testing.expectEqual(fHello.step(3, 0, 0, 0, false, false), .{ .x = 3, .y = 0 }); + try std.testing.expectEqual(fHello.step(3, 0, 1, 0, false, false), .{ .x = 4, .y = 0 }); + try std.testing.expectEqual(fHello.step(0, 0, -1, 0, false, false), .{ .x = 23, .y = 0 }); } }; diff --git a/src/pointer.zig b/src/pointer.zig index 653f890..75bc5ae 100644 --- a/src/pointer.zig +++ b/src/pointer.zig @@ -40,18 +40,20 @@ pub const Pointer = struct { switch (c) { '@' => return pointerReturn{}, 'z' => {}, - '#' => p.step(), + '#' => { + p.step(false); + }, 'j' => { var n = p.ss.toss.pop(); var j: usize = 0; if (n > 0) { while (j < n) : (j += 1) { - p.step(); + p.step(false); } } else { p.reverse(); while (j < -n) : (j += 1) { - p.step(); + p.step(false); } p.reverse(); } @@ -61,9 +63,9 @@ pub const Pointer = struct { const x = p.x; const y = p.y; const n = p.ss.toss.pop(); - var v = p.stepAndGet(); + var v = p.stepAndGet(false); var jumpingMode = false; - while (jumpingMode or v == ' ' or v == ';') : (v = p.stepAndGet()) { + while (jumpingMode or v == ' ' or v == ';') : (v = p.stepAndGet(false)) { if (v == ';') jumpingMode = !jumpingMode; } if (n > 0) { @@ -147,9 +149,11 @@ pub const Pointer = struct { } }, '"' => p.stringMode = true, - '\'' => try p.ss.toss.push(p.stepAndGet()), + '\'' => { + try p.ss.toss.push(p.stepAndGet(false)); + }, 's' => { - p.step(); + p.step(false); try p.field.set(p.x, p.y, p.ss.toss.pop()); }, '$' => _ = p.ss.toss.pop(), @@ -331,7 +335,7 @@ pub const Pointer = struct { if (self.stringMode) { if (self.lastCharWasSpace) { while (c == ' ') { - c = self.stepAndGet(); + c = self.stepAndGet(false); } self.lastCharWasSpace = false; } @@ -345,11 +349,11 @@ pub const Pointer = struct { var jumpingMode = false; while (jumpingMode or c == ' ' or c == ';') { if (c == ';') jumpingMode = !jumpingMode; - c = self.stepAndGet(); + c = self.stepAndGet(false); } result = try self.eval(ioContext, c); } - self.step(); + self.step(!self.stringMode); return result; } pub fn init(allocator: std.mem.Allocator, f: *field.Field, timestamp: ?i64, argv: []const []const u8, env: []const [*:0]const u8) !*Pointer { @@ -423,13 +427,13 @@ pub const Pointer = struct { p.dx = -p.dx; p.dy = -p.dy; } - inline fn step(self: *Pointer) void { - const v = self.field.step(self.x, self.y, self.dx, self.dy); + inline fn step(self: *Pointer, smartAdvance: bool) void { + const v = self.field.step(self.x, self.y, self.dx, self.dy, smartAdvance, false); self.x = v.x; self.y = v.y; } - inline fn stepAndGet(self: *Pointer) i64 { - self.step(); + inline fn stepAndGet(self: *Pointer, smartAdvance: bool) i64 { + self.step(smartAdvance); return self.field.get(self.x, self.y); } }; |