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 }