const std = @import("std"); const langs = @import("lang.zig"); const runners = @import("runner.zig"); const printer = @import("printer.zig"); test "scritcher" { _ = @import("lang.zig"); _ = @import("runner.zig"); } pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var stdout_file = try std.io.getStdOut(); const stdout = &stdout_file.outStream().stream; const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path")); var file = try std.fs.File.openWrite(scri_path); defer file.close(); var out = file.outStream(); var stream = &out.stream; // the thing here is that 'load :0' would load the scri_path, since we // now have a 'repl' argument right before it. to counteract that, the // initial repl buffer contains 'load :1' instead. var cmds = langs.CommandList.init(allocator); defer cmds.deinit(); var loadargs = langs.ArgList.init(allocator); defer loadargs.deinit(); try loadargs.append(":1"); try cmds.append(langs.Command{ .command = .Load, .args = loadargs, }); // TODO start a runner and keep it hot var lang = langs.Lang.init(allocator); defer lang.deinit(); while (true) { try stdout.print("> "); var buffer = try std.Buffer.init(allocator, ""[0..]); var line = std.io.readLine(&buffer) catch |err| { if (err == error.EndOfStream) break; return err; }; var cmds_parsed = lang.parse(line) catch |err| { std.debug.warn("repl: error while parsing: {}\n", err); continue; }; try cmds.append(cmds_parsed.at(0)); lang.reset(); // TODO save the line to scri_file? or should we have a special `push` // to do so? try file.seekTo(0); try printer.printList(cmds, stream); } } pub fn main() !void { const allocator = std.heap.direct_allocator; var lang = langs.Lang.init(allocator); defer lang.deinit(); var runner = runners.Runner.init(allocator); defer runner.deinit(); var args_it = std.process.args(); // TODO print help _ = try (args_it.next(allocator) orelse @panic("expected exe name")); const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path")); if (std.mem.eql(u8, scri_path, "repl")) { return try doRepl(allocator, &args_it); } var file = try std.fs.File.openRead(scri_path); defer file.close(); // sadly, we read it all into memory. such is life const total_bytes = try file.getEndPos(); var data = try allocator.alloc(u8, total_bytes); defer allocator.free(data); _ = try file.read(data); var cmds = try lang.parse(data); defer cmds.deinit(); try runner.runCommands(cmds, true); }