···11# Ziglings
2233Welcome to Ziglings! This project contains a series of tiny
44-broken programs (and one nasty surprise). By fixing them, you'll
44+broken programs (and one nasty surprise). By fixing them, you'll
55learn how to read and write [Zig](https://ziglang.org/) code.
6677
+57-31
build.zig
···1515// 1) Getting Started
1616// 2) Version Changes
1717comptime {
1818- const required_zig = "0.16.0";
1818+ const required_zig = "0.16.0-dev.2915";
1919 const current_zig = builtin.zig_version;
2020 const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable;
2121 if (current_zig.order(min_zig) == .lt) {
···205205 break :blk seed;
206206 });
207207 const rnd = prng.random();
208208- const ex = exercises[rnd.intRangeLessThan(usize, 0, exercises.len)];
208208+ const num = rnd.intRangeLessThan(usize, 0, exercises.len);
209209+ const ex = exercises[num];
209210210211 print("random exercise: {s}\n", .{ex.main_file});
211212···270271271272 const progress_file_size = try progress_file.length(io);
272273273273- var gpa = std.heap.DebugAllocator(.{}){};
274274- defer _ = gpa.deinit();
275275- const allocator = gpa.allocator();
276276- const contents = try allocator.alloc(u8, progress_file_size);
277277- defer allocator.free(contents);
274274+ var gpa = b.allocator;
275275+ const contents = try gpa.alloc(u8, progress_file_size);
276276+ defer gpa.free(contents);
278277 var file_buffer: [1024]u8 = undefined;
279278 var file_reader = progress_file.reader(io, &file_buffer);
280279 // try file_reader.interface.readSliceAll(contents);
···346345 return self;
347346 }
348347348348+ fn printProgress(num: usize, max: usize) void {
349349+ const bar_width: u32 = 60;
350350+351351+ const filled_len_u64 = (@as(u64, num) * bar_width) / max;
352352+ const filled_len = @as(u32, @intCast(filled_len_u64));
353353+354354+ var bar_buf: [bar_width]u8 = undefined;
355355+356356+ for (0..bar_width) |n| {
357357+ const ord = std.math.order(n, filled_len);
358358+ bar_buf[n] = switch (ord) {
359359+ .lt => '#',
360360+ .eq => '>',
361361+ .gt => '-',
362362+ };
363363+ }
364364+365365+ std.debug.print("\rProgress: [{s}] {d}/{d}\n\n", .{ &bar_buf, num, max });
366366+ }
367367+349368 fn make(step: *Step, options: Step.MakeOptions) !void {
350369 // NOTE: Using exit code 2 will prevent the Zig compiler to print the message:
351370 // "error: the following build command failed with exit code 1:..."
···360379 print("\n\n", .{});
361380 return;
362381 }
382382+383383+ // Progess
384384+ printProgress(self.exercise.number(), exercises.len - 1);
363385364386 const exe_path = self.compile(options.progress_node) catch {
365387 self.printErrors();
···388410 fn run(self: *ZiglingStep, exe_path: []const u8, _: std.Progress.Node) !void {
389411 resetLine();
390412 const b = self.step.owner;
413413+ const gpa = b.allocator;
391414 const io = b.graph.io;
392415393416 print("Checking: {s}\n", .{self.exercise.main_file});
···395418 // Allow up to 1 MB of stdout capture.
396419 const max_output_bytes = 1 * 1024 * 1024;
397420398398- const result = Process.run(b.allocator, io, .{
421421+ const result = Process.run(gpa, io, .{
399422 .argv = &.{exe_path},
400423 .cwd = .{ .path = b.build_root.path.? },
401424 .stdout_limit = .limited(max_output_bytes),
···413436414437 fn check_output(self: *ZiglingStep, result: Process.RunResult) !void {
415438 const b = self.step.owner;
439439+ const gpa = b.allocator;
416440 const io = b.graph.io;
417441418442 // Make sure it exited cleanly.
···438462439463 // NOTE: exercise.output can never contain a CR character.
440464 // See https://ziglang.org/documentation/master/#Source-Encoding.
441441- const output = trimLines(b.allocator, raw_output) catch @panic("OOM");
465465+ const output = trimLines(gpa, raw_output) catch @panic("OOM");
442466443467 // Validate the output.
444468 var exercise_output = self.exercise.output;
···486510 , .{ red, reset, exercise_output, red, reset, output, red, reset });
487511 }
488512489489- const progress = try std.fmt.allocPrint(b.allocator, "{d}", .{self.exercise.number()});
490490- defer b.allocator.free(progress);
513513+ const progress = try std.fmt.allocPrint(gpa, "{d}", .{self.exercise.number()});
514514+ defer gpa.free(progress);
491515492516 const file = try std.Io.Dir.cwd().createFile(
493517 io,
···526550 print("Compiling: {s}\n", .{self.exercise.main_file});
527551528552 const b = self.step.owner;
553553+ const gpa = b.allocator;
529554 const exercise_path = self.exercise.main_file;
530530- const path = join(b.allocator, &.{ self.work_path, exercise_path }) catch
555555+ const path = join(gpa, &.{ self.work_path, exercise_path }) catch
531556 @panic("OOM");
532557533533- var zig_args = std.array_list.Managed([]const u8).init(b.allocator);
534534- defer zig_args.deinit();
558558+ var zig_args = std.ArrayList([]const u8).initCapacity(gpa, 10) catch @panic("OOM");
559559+ defer zig_args.deinit(gpa);
535560536536- zig_args.append(b.graph.zig_exe) catch @panic("OOM");
561561+ zig_args.append(gpa, b.graph.zig_exe) catch @panic("OOM");
537562538563 const cmd = switch (self.exercise.kind) {
539564 .exe => "build-exe",
540565 .@"test" => "test",
541566 };
542542- zig_args.append(cmd) catch @panic("OOM");
567567+ zig_args.append(gpa, cmd) catch @panic("OOM");
543568544569 // Enable C support for exercises that use C functions.
545570 if (self.exercise.link_libc) {
546546- zig_args.append("-lc") catch @panic("OOM");
547547- zig_args.append("-fllvm") catch @panic("OOM");
571571+ zig_args.append(gpa, "-lc") catch @panic("OOM");
572572+ zig_args.append(gpa, "-fllvm") catch @panic("OOM");
548573 }
549574550575 if (b.reference_trace) |rt| {
551551- zig_args.append(b.fmt("-freference-trace={}", .{rt})) catch @panic("OOM");
576576+ zig_args.append(gpa, b.fmt("-freference-trace={}", .{rt})) catch @panic("OOM");
552577 }
553578554554- zig_args.append(b.pathFromRoot(path)) catch @panic("OOM");
579579+ zig_args.append(gpa, b.pathFromRoot(path)) catch @panic("OOM");
555580556556- zig_args.append("--cache-dir") catch @panic("OOM");
557557- zig_args.append(b.pathFromRoot(b.cache_root.path.?)) catch @panic("OOM");
581581+ zig_args.append(gpa, "--cache-dir") catch @panic("OOM");
582582+ zig_args.append(gpa, b.pathFromRoot(b.cache_root.path.?)) catch @panic("OOM");
558583559559- zig_args.append("--listen=-") catch @panic("OOM");
584584+ zig_args.append(gpa, "--listen=-") catch @panic("OOM");
560585561586 //
562587 // NOTE: After many changes in zig build system, we need to create the cache path manually.
563588 // See https://github.com/ziglang/zig/pull/21115
564589 // Maybe there is a better way (in the future).
565565- const exe_dir = try self.step.evalZigProcess(zig_args.items, prog_node, false, null, b.allocator);
590590+ const exe_dir = try self.step.evalZigProcess(zig_args.items, prog_node, false, null, gpa);
566591 const exe_name = switch (self.exercise.kind) {
567592 .exe => self.exercise.name(),
568593 .@"test" => "test",
···628653629654/// Removes trailing whitespace for each line in buf, also ensuring that there
630655/// are no trailing LF characters at the end.
631631-pub fn trimLines(allocator: std.mem.Allocator, buf: []const u8) ![]const u8 {
632632- var list = try std.array_list.Aligned(u8, null).initCapacity(allocator, buf.len);
656656+pub fn trimLines(gpa: std.mem.Allocator, buf: []const u8) ![]const u8 {
657657+ var list = try std.ArrayList(u8).initCapacity(gpa, buf.len);
658658+ errdefer list.deinit(gpa);
633659634660 var iter = std.mem.splitSequence(u8, buf, " \n");
635661 while (iter.next()) |line| {
636662 // TODO: trimming CR characters is probably not necessary.
637663 const data = std.mem.trimEnd(u8, line, " \r");
638638- try list.appendSlice(allocator, data);
639639- try list.append(allocator, '\n');
664664+ try list.appendSlice(gpa, data);
665665+ try list.append(gpa, '\n');
640666 }
641667642642- const result = try list.toOwnedSlice(allocator); // TODO: probably not necessary
668668+ // Calls deinit()
669669+ const result = try list.toOwnedSlice(gpa);
643670644644- // Remove the trailing LF character, that is always present in the exercise
645645- // output.
671671+ // Remove the trailing LF character, that is always present in the exercise output.
646672 return std.mem.trimEnd(u8, result, "\n");
647673}
648674