1
0
Fork 0

Ensure the pointer always ends up on an executable instruction for tui consistency

This commit is contained in:
Julien Dessaux 2022-12-04 05:24:23 +01:00
parent b373cbffa1
commit 2517e44899
Signed by: adyxax
GPG key ID: F92E51B86E07177E
2 changed files with 48 additions and 30 deletions

View file

@ -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 });
}
};

View file

@ -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);
}
};