const std = @import("std"); const runners = @import("runner.zig"); const Allocator = std.mem.Allocator; pub const Result = error{ Ok, ScannerError, CompileError, }; fn run(allocator: *Allocator, data: []const u8) !void { var stdout_file = std.io.getStdOut(); const stdout = stdout_file.outStream(); var runner = runners.Runner.init(allocator, stdout); return runner.execute(data); } fn runFile(allocator: *Allocator, path: []const u8) !void { var file = try std.fs.cwd().openFile(path, .{}); defer file.close(); const total_bytes = try file.getEndPos(); var slice = try allocator.alloc(u8, total_bytes); _ = try file.read(slice); run(allocator, slice) catch |err| { switch (err) { Result.Ok => {}, Result.CompileError => std.os.exit(65), else => return err, } }; } fn runPrompt(allocator: *Allocator) !void { var stdout_file = std.io.getStdOut(); const stdout = stdout_file.outStream(); var stdin_file = std.io.getStdIn(); const stdin = stdin_file.inStream(); var line_buf: [1024]u8 = undefined; while (true) { try stdout.print("> ", .{}); const amt = try stdin.read(&line_buf); if (amt == line_buf.len) { try stdout.print("Input too long.\n", .{}); continue; } const line = std.mem.trimRight(u8, line_buf[0..amt], "\r\n"); run(allocator, line) catch |err| { switch (err) { Result.Ok => {}, Result.ScannerError => blk: { try stdout.print("scanner error.\n", .{}); }, Result.CompileError => blk: { try stdout.print("compile error.\n", .{}); }, else => return err, } }; } } pub fn main() anyerror!void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); var allocator = &arena.allocator; var stdout_file = std.io.getStdOut(); var stdout = stdout_file.outStream(); var args_it = std.process.args(); _ = args_it.next(allocator); var filePath = try (args_it.next(allocator) orelse { try runPrompt(allocator); return; }); try runFile(allocator, filePath); }