1
0
Fork 0

zig 0.11 changes

This commit is contained in:
Julien Dessaux 2023-12-18 07:26:01 +01:00
parent 8b3b7582c2
commit 83af8ab124
Signed by: adyxax
GPG key ID: F92E51B86E07177E
10 changed files with 152 additions and 103 deletions

View file

@ -17,7 +17,7 @@ Current limitations are :
## Dependencies
zig is required. Only zig version >= 0.10.1 on linux amd64 (Gentoo) is being regularly tested.
zig is required. Only zig version 0.11 on linux amd64 (Gentoo) is being regularly tested.
## Quick Install
@ -58,7 +58,7 @@ zig build
For a non debug build, use either one of:
```sh
zig build -Drelease-safe
zig build -Drelease-small
zig build -Drelease-fast
zig build -Doptimize=ReleaseSafe
zig build -Doptimize=ReleaseSmall
zig build -Doptimize=ReleaseFast
```

View file

@ -1,45 +1,32 @@
const std = @import("std");
pub fn build(b: *std.build.Builder) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Standard release options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
const mode = b.standardReleaseOptions();
const exe = b.addExecutable("zigfunge98", "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.install();
const run_cmd = exe.run();
const exe = b.addExecutable(.{
.name = "zigfunge98",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const tui = b.addExecutable("zigfunge98-tui", "src/tui.zig");
tui.addPackagePath("spoon", "lib/spoon/import.zig");
tui.setTarget(target);
tui.setBuildMode(mode);
tui.install();
const coverage = b.option(bool, "test-coverage", "Generate test coverage") orelse false;
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
const unit_tests = b.addTest(.{
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
const exe_tests = b.addTest("src/main.zig");
exe_tests.setTarget(target);
exe_tests.setBuildMode(mode);
const coverage = b.option(bool, "test-coverage", "Generate test coverage") orelse false;
// Code coverage with kcov, we need an allocator for the setup
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = general_purpose_allocator.deinit();
const gpa = general_purpose_allocator.allocator();
// We want to exclude the $HOME/.zig path
const home = std.process.getEnvVarOwned(gpa, "HOME") catch "";
@ -47,7 +34,8 @@ pub fn build(b: *std.build.Builder) void {
const exclude = std.fmt.allocPrint(gpa, "--exclude-path={s}/.zig/", .{home}) catch "";
defer gpa.free(exclude);
if (coverage) {
exe_tests.setExecCmd(&[_]?[]const u8{
unit_tests.test_runner = "/usr/bin/kcov";
unit_tests.setExecCmd(&[_]?[]const u8{
"kcov",
exclude,
//"--path-strip-level=3", // any kcov flags can be specified here
@ -56,6 +44,35 @@ pub fn build(b: *std.build.Builder) void {
});
}
const run_unit_tests = b.addRunArtifact(unit_tests);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&exe_tests.step);
test_step.dependOn(&run_unit_tests.step);
// ----- TUI --------------------------------------------------------------
const tui = b.addExecutable(.{
.name = "zigfunge98-tui",
.root_source_file = .{ .path = "src/tui.zig" },
.target = target,
.optimize = optimize,
});
const spoon = b.createModule(.{
.source_file = .{ .path = "lib/spoon/import.zig" },
});
tui.addModule("spoon", spoon);
b.installArtifact(tui);
const tui_cmd = b.addRunArtifact(tui);
tui_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
tui_cmd.addArgs(args);
}
const tui_step = b.step("run-tui", "Run the app");
tui_step.dependOn(&tui_cmd.step);
const tui_unit_tests = b.addTest(.{
.root_source_file = .{ .path = "src/tui.zig" },
.target = target,
.optimize = optimize,
});
const tui_run_unit_tests = b.addRunArtifact(tui_unit_tests);
const tui_test_step = b.step("test-tui", "Run tui unit tests");
tui_test_step.dependOn(&tui_run_unit_tests.step);
}

@ -1 +1 @@
Subproject commit 75dbab71771ca2ee5aadcd5ab7a4c503a9536031
Subproject commit 9fa5bb1eafc30b3ff0cbe297a3e0f51dbc903831

View file

@ -5,17 +5,17 @@ const Line = struct {
x: i64 = 0,
data: std.ArrayList(i64),
fn blank(l: *Line, x: i64) void {
const lx = @intCast(i64, l.len());
const lx: i64 = @intCast(l.len());
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)] = ' ';
l.data.items[@intCast(x - l.x)] = ' ';
} else if (lx == 1) { // this was the last character on the line
l.data.items.len = 0;
} else if (x == l.x) { // we need to remove leading spaces
var i: usize = 1;
while (l.data.items[i] == ' ') : (i += 1) {}
l.x += @intCast(i64, i);
l.x += @intCast(i);
std.mem.copy(i64, l.data.items[0 .. l.len() - i], l.data.items[i..]);
l.data.items.len -= i;
} else { // we need to remove trailing spaces
@ -66,7 +66,8 @@ const Line = struct {
self.allocator.destroy(self);
}
fn get(l: *Line, x: i64) i64 {
if (x >= l.x and x < l.x + @intCast(i64, l.len())) return l.data.items[@intCast(usize, x - @intCast(i64, l.x))];
const ll: i64 = @intCast(l.len());
if (x >= l.x and x < l.x + ll) return l.data.items[@intCast(x - l.x)];
return ' ';
}
fn init(allocator: std.mem.Allocator) !*Line {
@ -84,10 +85,10 @@ const Line = struct {
try l.data.append(v);
return;
}
const lx = @intCast(i64, l.len());
const lx: i64 = @intCast(l.len());
if (x >= l.x) {
if (x < l.x + lx) { // just set the value
l.data.items[@intCast(usize, x - l.x)] = v;
l.data.items[@intCast(x - l.x)] = v;
} else { // we need to add trailing spaces
var i: usize = l.len();
while (i < x - l.x) : (i += 1) {
@ -97,12 +98,12 @@ const Line = struct {
}
} else { // we need to shift right and add leading spaces
const oldLen = l.len();
l.data.items.len += @intCast(usize, l.x - x);
l.data.items.len += @intCast(l.x - x);
try l.data.ensureUnusedCapacity(l.len());
std.mem.copyBackwards(i64, l.data.items[@intCast(usize, l.x - x)..], l.data.items[0..oldLen]);
std.mem.copyBackwards(i64, l.data.items[@intCast(l.x - x)..], l.data.items[0..oldLen]);
l.data.items[0] = v;
var i: usize = 1;
while (i < @intCast(usize, l.x - x)) : (i += 1) {
while (i < l.x - x) : (i += 1) {
l.data.items[i] = ' ';
}
l.x = x;
@ -150,10 +151,11 @@ pub const Field = struct {
lines: std.ArrayList(*Line),
lx: usize = 0,
pub fn blank(f: *Field, x: i64, y: i64) !void {
const ly = @intCast(i64, f.lines.items.len);
const ly = f.lines.items.len;
if (ly == 0) return error.EmptyFieldError;
if (y < f.y or y >= f.y + ly) return; // outside the field
var l = f.lines.items[@intCast(usize, y - f.y)];
const lly: i64 = @intCast(ly);
if (y < f.y or y >= f.y + lly) return; // outside the field
var l = f.lines.items[@intCast(y - f.y)];
if (l.len() == 0) return; // the line is already empty
l.blank(x);
if (l.len() == 0) {
@ -165,27 +167,29 @@ pub const Field = struct {
while (f.lines.items[i].len() == 0) : (i += 1) {
f.lines.items[i].deinit();
}
f.y += @intCast(i64, i);
f.y += @intCast(i);
std.mem.copy(*Line, f.lines.items[0 .. f.lines.items.len - i], f.lines.items[i..]);
f.lines.items.len -= i;
} else if (y == f.y + ly - 1) { // we need to remove trailing lines
} else if (y == f.y + lly - 1) { // we need to remove trailing lines
l.deinit();
var i: usize = @intCast(usize, ly) - 2;
var i: usize = ly - 2;
while (f.lines.items[i].len() == 0) : (i -= 1) {
f.lines.items[i].deinit();
}
f.lines.items.len = i + 1;
}
}
if (x == f.x or x == f.x + @intCast(i64, f.lx) - 1) { // recalculate boundaries
const flx: i64 = @intCast(f.lx);
if (x == f.x or x == f.x + flx - 1) { // recalculate boundaries
f.x = std.math.maxInt(i64);
var x2: i64 = std.math.minInt(i64);
for (f.lines.items) |line| {
if (line.len() == 0) continue;
if (f.x > line.x) f.x = line.x;
if (x2 < line.x + @intCast(i64, line.len())) x2 = line.x + @intCast(i64, line.len());
const ll: i64 = @intCast(line.len());
if (x2 < line.x + ll) x2 = line.x + ll;
}
f.lx = @intCast(usize, x2 - f.x);
f.lx = @intCast(x2 - f.x);
}
}
test "blank" {
@ -241,11 +245,12 @@ pub const Field = struct {
self.allocator.destroy(self);
}
pub fn get(f: *Field, x: i64, y: i64) i64 {
if (y >= f.y and y < f.y + @intCast(i64, f.lines.items.len)) return f.lines.items[@intCast(usize, y - @intCast(i64, f.y))].get(x);
const fl: i64 = @intCast(f.lines.items.len);
if (y >= f.y and y < f.y + fl) return f.lines.items[@intCast(y - f.y)].get(x);
return ' ';
}
pub fn getSize(f: Field) [4]i64 {
return [4]i64{ f.x, f.y, @intCast(i64, f.lx), @intCast(i64, f.lines.items.len) };
return [4]i64{ f.x, f.y, @intCast(f.lx), @intCast(f.lines.items.len) };
}
fn init(allocator: std.mem.Allocator) !*Field {
var f = try allocator.create(Field);
@ -266,7 +271,9 @@ pub const Field = struct {
return f;
}
inline fn isIn(f: *Field, x: i64, y: i64) bool {
return x >= f.x and y >= f.y and x < f.x + @intCast(i64, f.lx) and y < f.y + @intCast(i64, f.lines.items.len);
const fl: i64 = @intCast(f.lines.items.len);
const flx: i64 = @intCast(f.lx);
return x >= f.x and y >= f.y and x < f.x + flx and y < f.y + fl;
}
fn load(f: *Field, reader: anytype) !void {
if (f.lines.items.len > 1 or f.lx > 0) return error.FIELD_NOT_EMPTY;
@ -334,8 +341,9 @@ pub const Field = struct {
pub fn set(f: *Field, x: i64, y: i64, v: i64) !void {
if (v == ' ') return f.blank(x, y);
if (y >= f.y) {
if (y < f.y + @intCast(i64, f.lines.items.len)) { // the line exists
try f.lines.items[@intCast(usize, y - f.y)].set(x, v);
const fl: i64 = @intCast(f.lines.items.len);
if (y < f.y + fl) { // the line exists
try f.lines.items[@intCast(y - f.y)].set(x, v);
} else { // append lines
var i: usize = f.lines.items.len;
while (i < y - f.y) : (i += 1) {
@ -347,27 +355,30 @@ pub const Field = struct {
}
} else { // preprend lines
const oldLen = f.lines.items.len;
f.lines.items.len += @intCast(usize, f.y - y);
const dl: usize = @intCast(f.y - y);
f.lines.items.len += dl;
try f.lines.ensureUnusedCapacity(f.lines.items.len);
std.mem.copyBackwards(*Line, f.lines.items[@intCast(usize, f.y - y)..], f.lines.items[0..oldLen]);
std.mem.copyBackwards(*Line, f.lines.items[dl..], f.lines.items[0..oldLen]);
var l = try Line.init(f.allocator);
try l.set(x, v);
f.lines.items[0] = l;
var i: usize = 1;
while (i < @intCast(usize, f.y - y)) : (i += 1) {
while (i < f.y - y) : (i += 1) {
f.lines.items[i] = try Line.init(f.allocator);
}
f.y = y;
}
if (x < f.x or x >= f.x + @intCast(i64, f.lx)) { // recalculate boundaries
const flx: i64 = @intCast(f.lx);
if (x < f.x or x >= f.x + flx) { // recalculate boundaries
f.x = std.math.maxInt(i64);
var x2: i64 = std.math.minInt(i64);
for (f.lines.items) |line| {
if (line.len() == 0) continue;
if (f.x > line.x) f.x = line.x;
if (x2 < line.x + @intCast(i64, line.len())) x2 = line.x + @intCast(i64, line.len());
const ll: i64 = @intCast(line.len());
if (x2 < line.x + ll) x2 = line.x + ll;
}
f.lx = @intCast(usize, x2 - f.x);
f.lx = @intCast(x2 - f.x);
}
return;
}

View file

@ -60,7 +60,11 @@ pub fn Context(comptime readerType: anytype, comptime writerType: anytype) type
try std.testing.expectEqual(ioContext.decimalInput(), error.IOError);
}
pub fn characterOutput(self: Self, v: i64) !void {
try self.writer.print("{c}", .{@intCast(u8, v)});
var vv: u8 = '?';
if (v >= 0 and v <= 255) {
vv = @intCast(v);
}
try self.writer.print("{c}", .{vv});
return;
}
pub fn decimalOutput(self: Self, v: i64) !void {

View file

@ -3,10 +3,10 @@ const interpreter = @import("interpreter.zig");
const io = @import("io.zig");
pub fn main() anyerror!void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(!gpa.deinit());
var args = try std.process.argsAlloc(gpa.allocator());
defer std.process.argsFree(gpa.allocator(), args);
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
const gpa = general_purpose_allocator.allocator();
var args = try std.process.argsAlloc(gpa);
defer std.process.argsFree(gpa, args);
if (args.len < 2) {
std.debug.print("Usage: {s} <b98_file_to_run>\n", .{args[0]});
std.os.exit(1);
@ -16,11 +16,11 @@ pub fn main() anyerror!void {
defer file.close();
const env: []const [*:0]const u8 = std.os.environ;
var i = try interpreter.Interpreter.init(gpa.allocator(), file.reader(), null, args, env[0..]);
var i = try interpreter.Interpreter.init(gpa, file.reader(), null, args, env[0..]);
defer i.deinit();
var ioContext = io.context(std.io.getStdIn().reader(), std.io.getStdOut().writer());
std.os.exit(@intCast(u8, try i.run(&ioContext)));
std.os.exit(@intCast(try i.run(&ioContext)));
}
const testTimestamp: i64 = 1660681247;

View file

@ -245,21 +245,26 @@ pub const Pointer = struct {
// 18
i = 0;
while (i < p.ss.data.items.len) : (i += 1) {
try p.ss.toss.push(@intCast(i64, p.ss.data.items[i].data.items.len));
try p.ss.toss.push(@intCast(p.ss.data.items[i].data.items.len));
}
try p.ss.toss.push(@intCast(i64, height));
try p.ss.toss.push(@intCast(height));
// 17
try p.ss.toss.push(@intCast(i64, p.ss.data.items.len) + 1);
try p.ss.toss.push(@intCast(p.ss.data.items.len + 1));
// 16
const ts = if (p.timestamp) |v| v else std.time.timestamp();
const now = std.time.epoch.EpochSeconds{ .secs = @intCast(u64, ts) };
const now = std.time.epoch.EpochSeconds{ .secs = @intCast(ts) };
const epochDay = now.getEpochDay();
const daySeconds = now.getDaySeconds();
try p.ss.toss.push(@intCast(i64, daySeconds.getHoursIntoDay()) * 256 * 256 + @intCast(i64, daySeconds.getMinutesIntoHour()) * 256 + @intCast(i64, daySeconds.getSecondsIntoMinute()));
const hours: i64 = @intCast(daySeconds.getHoursIntoDay());
const minutes: i64 = @intCast(daySeconds.getMinutesIntoHour());
const seconds: i64 = @intCast(daySeconds.getSecondsIntoMinute());
try p.ss.toss.push(hours * 256 * 256 + minutes * 256 + seconds);
// 15
const yearAndDay = epochDay.calculateYearDay();
const year: i64 = @intCast(yearAndDay.year);
const monthAndDay = yearAndDay.calculateMonthDay();
try p.ss.toss.push(@intCast(i64, yearAndDay.year - 1900) * 256 * 256 + @intCast(i64, monthAndDay.month.numeric()) * 256 + @intCast(i64, monthAndDay.day_index));
const month: i64 = @intCast(monthAndDay.month.numeric());
try p.ss.toss.push((year - 1900) * 256 * 256 + month * 256 + monthAndDay.day_index);
// 14
try p.ss.toss.pushVector([2]i64{ fieldSize[2] - 1, fieldSize[3] - 1 });
// 13
@ -289,7 +294,7 @@ pub const Pointer = struct {
// 1
try p.ss.toss.push(0b00000); // TODO update when implementing t, i, o and =
if (n > 0) {
try p.ss.toss.yCommandPick(@intCast(usize, n), height);
try p.ss.toss.yCommandPick(@intCast(n), height);
}
},
'(' => {

View file

@ -1,5 +1,5 @@
const std = @import("std");
const vector = std.meta.Vector(2, i64);
const vector = @Vector(2, i64);
pub const Stack = struct {
allocator: std.mem.Allocator,
@ -78,7 +78,7 @@ pub const Stack = struct {
// (aka begin) and '}' (aka end) stackstack commands
try toss.data.ensureUnusedCapacity(n);
var i: usize = n;
while (i >= std.math.min(soss.data.items.len, n) + 1) : (i -= 1) {
while (i >= @min(soss.data.items.len, n) + 1) : (i -= 1) {
toss.data.appendAssumeCapacity(0);
}
while (i >= 1) : (i -= 1) {

View file

@ -28,7 +28,7 @@ pub const StackStack = struct {
const n = soss.pop();
self.toss = try stack.Stack.init(self.allocator);
if (n > 0) {
try self.toss.transfert(soss, @intCast(u64, n));
try self.toss.transfert(soss, @intCast(n));
} else if (n < 0) {
var i: usize = 0;
while (i < -n) : (i += 1) {
@ -85,9 +85,11 @@ pub const StackStack = struct {
const n = self.toss.pop();
const v = soss.popVector();
if (n > 0) {
try soss.transfert(self.toss, @intCast(u64, n));
const nn: usize = @intCast(n);
try soss.transfert(self.toss, nn);
} else {
soss.discard(@intCast(u64, -n));
const nn: usize = @intCast(-n);
soss.discard(nn);
}
self.toss.deinit();
self.toss = soss;

View file

@ -9,10 +9,10 @@ var intp: *interpreter.Interpreter = undefined;
pub fn main() anyerror!void {
//--- befunge initialization ----------------------------------------------
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(!gpa.deinit());
args = try std.process.argsAlloc(gpa.allocator());
defer std.process.argsFree(gpa.allocator(), args);
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
const gpa = general_purpose_allocator.allocator();
args = try std.process.argsAlloc(gpa);
defer std.process.argsFree(gpa, args);
if (args.len < 2) {
std.debug.print("Usage: {s} <b98_file_to_run>\n", .{args[0]});
std.os.exit(1);
@ -22,7 +22,7 @@ pub fn main() anyerror!void {
defer file.close();
const env: []const [*:0]const u8 = std.os.environ;
intp = try interpreter.Interpreter.init(gpa.allocator(), file.reader(), null, args, env[0..]);
intp = try interpreter.Interpreter.init(gpa, file.reader(), null, args, env[0..]);
defer intp.deinit();
var ioContext = io.context(std.io.getStdIn().reader(), std.io.getStdOut().writer()); // TODO io functions for tui
@ -38,11 +38,13 @@ pub fn main() anyerror!void {
}, null);
var fds: [1]std.os.pollfd = undefined;
fds[0] = .{
.fd = term.tty.handle,
.events = std.os.POLL.IN,
.revents = undefined,
};
if (term.tty) |tty| {
fds[0] = .{
.fd = tty,
.events = std.os.POLL.IN,
.revents = undefined,
};
}
try term.uncook(.{});
defer term.cook() catch {};
@ -68,9 +70,8 @@ pub fn main() anyerror!void {
term.deinit();
intp.deinit();
file.close();
std.process.argsFree(gpa.allocator(), args);
std.debug.assert(!gpa.deinit());
std.os.exit(@intCast(u8, code));
std.process.argsFree(gpa, args);
std.os.exit(@intCast(code));
}
try render();
}
@ -110,7 +111,8 @@ fn render() !void {
var s = rc.restrictedPaddingWriter(16);
const v = intp.pointer.ss.toss.data.items[n];
if (v >= 32 and v < 127) {
try s.writer().print("{c} - {d}", .{ @intCast(u8, v), v });
const tv: u8 = @intCast(v);
try s.writer().print("{c} - {d}", .{ tv, v });
} else {
try s.writer().print("{d}", .{v});
}
@ -119,28 +121,36 @@ fn render() !void {
try rc.moveCursorTo(2, 18);
try rc.setAttribute(.{ .fg = .blue, .reverse = true });
var fieldTitle = rc.restrictedPaddingWriter(term.width - 17);
const size = intp.field.getSize();
const sizei = intp.field.getSize();
const size = [4]usize{ @intCast(sizei[0]), @intCast(sizei[1]), @intCast(sizei[2]), @intCast(sizei[3]) };
try fieldTitle.writer().print("Funge field | top left corner:({d},{d}) size:{d}x{d}", .{ size[0], size[1], size[2], size[3] });
try fieldTitle.pad();
try rc.setAttribute(.{ .fg = .blue, .reverse = false });
var y: usize = 0; // TODO negative lines
while (y < @min(@intCast(usize, size[3]), term.height - 3)) : (y += 1) {
while (y < @min(size[3], term.height - 3)) : (y += 1) {
var field = rc.restrictedPaddingWriter(term.width - 17);
const line = intp.field.lines.items[y];
var x: usize = 0;
if (line.x >= 0) {
try rc.moveCursorTo(y + 3, 18 + @intCast(usize, line.x));
const lx: usize = @intCast(line.x);
try rc.moveCursorTo(y + 3, 18 + lx);
} else {
try rc.moveCursorTo(y + 3, 18); // TODO negative columns
}
while (x < @min(line.data.items.len, term.width - 18)) : (x += 1) {
var reset = false;
if (x + @intCast(usize, line.x) == intp.pointer.x and y == intp.pointer.y) { // TODO negatives
const xx: i64 = @intCast(x);
if (xx + line.x == intp.pointer.x and y == intp.pointer.y) { // TODO negatives
try rc.setAttribute(.{ .fg = .red, .reverse = true });
reset = true;
}
if (line.data.items[x] >= 32 and line.data.items[x] < 127) {
try field.writer().print("{c}", .{@intCast(u8, line.data.items[x])});
const v = line.data.items[x];
var vv: u8 = '?';
if (v >= 32 and v < 127) {
vv = @intCast(v);
}
try field.writer().print("{c}", .{vv});
} else {
try field.writer().writeAll("®");
}