common.zig (2358B) - raw
1 // Each program will have it's own `interpret` fn. This module holds all the other setup 2 // for running a bf program. 3 4 const std = @import("std"); 5 const Allocator = std.mem.Allocator; 6 const ArrayList = std.ArrayList; 7 8 const MEMORY_SIZE = 30000; 9 10 pub fn runInterpreter(parse: anytype, interpret: anytype) anyerror!void { 11 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); 12 defer arena.deinit(); 13 const alloc = arena.allocator(); 14 15 var args = std.process.args(); 16 _ = args.skip(); 17 const source_path = args.next() orelse return error.MissingSourcePathArg; 18 const f = try std.fs.cwd().openFile(source_path, .{}); 19 defer f.close(); 20 21 const src = try f.readToEndAlloc(alloc, 1024 * 20); 22 23 var stdin = std.io.getStdIn(); 24 var stdout = std.io.getStdOut(); 25 var memory = [_]u8{0} ** MEMORY_SIZE; 26 27 const program = try parse(src, alloc); 28 defer program.deinit(); 29 30 try interpret(program, &memory, stdin.reader(), stdout.writer(), alloc); 31 } 32 33 pub fn parseProgram(src: []const u8, alloc: std.mem.Allocator) !Program { 34 var instructions = ArrayList(u8).init(alloc); 35 36 for (src) |c| { 37 switch (c) { 38 '>', '<', '+', '-', '.', ',', '[', ']' => try instructions.append(c), 39 else => {}, 40 } 41 } 42 return .{ .instructions = try instructions.toOwnedSlice(), .alloc = alloc }; 43 } 44 45 pub const Program = struct { 46 alloc: Allocator, 47 instructions: []const u8, 48 49 fn deinit(self: Program) void { 50 self.alloc.free(self.instructions); 51 } 52 }; 53 54 pub fn testHelloWorld(parse: anytype, interpret: anytype) anyerror!void { 55 const expectEqualSlices = std.testing.expectEqualSlices; 56 57 const hello_world = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; 58 59 var list = ArrayList(u8).init(std.testing.allocator); 60 defer list.deinit(); 61 62 var in_buf: [0]u8 = undefined; 63 var empty_in = std.io.fixedBufferStream(&in_buf); 64 65 var memory = [_]u8{0} ** 30000; 66 const rdr = empty_in.reader(); 67 const wtr = list.writer(); 68 69 const program = try parse(hello_world, std.testing.allocator); 70 defer program.deinit(); 71 72 try interpret(program, &memory, rdr, wtr, std.testing.allocator); 73 std.debug.print("{s}", .{list.items}); 74 try expectEqualSlices(u8, "Hello World!\n", list.items); 75 }