From fc8dcf4583a42716e904f5c89e083b6ffceac78e Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 8 Sep 2019 17:06:19 -0300 Subject: [PATCH 01/11] add doRepl func --- src/main.zig | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main.zig b/src/main.zig index 156855e..4211446 100644 --- a/src/main.zig +++ b/src/main.zig @@ -7,6 +7,29 @@ test "scritcher" { _ = @import("runner.zig"); } +pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { + const scri_path = try (args_it.next(allocator) orelse @panic("expected scri path")); + + // 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 buf = langs.CommandList.init(allocator); + defer buf.deinit(); + + var loadargs = langs.ArgList.init(allocator); + defer loadargs.deinit(); + + try loadargs.append(":1"); + + try buf.append(langs.Command{ + .command = .Load, + .args = loadargs, + }); + + // TODO the rest +} + pub fn main() !void { const allocator = std.heap.direct_allocator; @@ -18,9 +41,15 @@ pub fn main() !void { 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(); From 34d3b12c56a6d49a9cd30e344769af2c6e5f0d7a Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 8 Sep 2019 17:27:59 -0300 Subject: [PATCH 02/11] add basic main loop --- src/main.zig | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main.zig b/src/main.zig index 4211446..fe3ce9a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -14,20 +14,35 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // now have a 'repl' argument right before it. to counteract that, the // initial repl buffer contains 'load :1' instead. - var buf = langs.CommandList.init(allocator); - defer buf.deinit(); + var cmds = langs.CommandList.init(allocator); + defer cmds.deinit(); var loadargs = langs.ArgList.init(allocator); defer loadargs.deinit(); try loadargs.append(":1"); - try buf.append(langs.Command{ + try cmds.append(langs.Command{ .command = .Load, .args = loadargs, }); - // TODO the rest + // TODO start a runner and keep it hot + + 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) return; + return err; + }; + + // TODO parse the line through langs.parse, then add the command to cmds + + // TODO save the line to scri_file? or should we have a special `push` + // to do so? + } } pub fn main() !void { From 736277db049fdffb6f8d3eddfde1bcd4c77fbc48 Mon Sep 17 00:00:00 2001 From: Luna Date: Sun, 8 Sep 2019 23:28:09 -0300 Subject: [PATCH 03/11] add parsing of given repl line --- src/lang.zig | 12 +++++------- src/main.zig | 12 +++++++++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 3af632c..fe31d11 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -3,10 +3,8 @@ const std = @import("std"); const plugin = @import("plugin.zig"); pub const ParseError = error{ - NoCommandGiven, - UnknownCommand, + OutOfMemory, ArgRequired, - FloatParseFail, ParseFail, }; @@ -261,7 +259,7 @@ pub const Lang = struct { fn expectAny(self: *Lang, count: usize, args: ArgList) !void { if (args.len != count) { - std.debug.warn("expected {} arguments, found {}\n", count, args.len); + self.doError("expected {} arguments, found {}", count, args.len); return error.ArgRequired; } } @@ -274,7 +272,7 @@ pub const Lang = struct { var i: usize = 0; if (args.len != count) { - std.debug.warn("expected {} arguments, found {}\n", count, args.len); + self.doError("expected {} arguments, found {}", count, args.len); return error.ArgRequired; } @@ -319,7 +317,7 @@ pub const Lang = struct { self.has_error = true; } - pub fn parse(self: *Lang, data: []const u8) !CommandList { + pub fn parse(self: *Lang, data: []const u8) ParseError!CommandList { var splitted_it = std.mem.separate(data, ";"); try self.fillKeywords(); var cmds = CommandList.init(self.allocator); @@ -359,7 +357,7 @@ pub const Lang = struct { // construct final Command based on command var cmd = Command{ .command = ctype, .args = args }; self.validateCommand(cmd) catch |err| { - self.doError("Unknown command '{}' (length {})", command, command.len); + //self.doError("error validating command '{}': {}", command, err); continue; }; diff --git a/src/main.zig b/src/main.zig index fe3ce9a..1ac9680 100644 --- a/src/main.zig +++ b/src/main.zig @@ -8,6 +8,9 @@ test "scritcher" { } 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")); // the thing here is that 'load :0' would load the scri_path, since we @@ -29,6 +32,9 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // TODO start a runner and keep it hot + var lang = langs.Lang.init(allocator); + defer lang.deinit(); + while (true) { try stdout.print("> "); @@ -38,7 +44,11 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { return err; }; - // TODO parse the line through langs.parse, then add the command to cmds + 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)); // TODO save the line to scri_file? or should we have a special `push` // to do so? From 8b67ccc1bfc0944720d3ffc0cc583658f1c07a04 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 10 Sep 2019 11:45:04 -0300 Subject: [PATCH 04/11] add printing of commands to any stream --- src/main.zig | 4 ++++ src/printer.zig | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/printer.zig diff --git a/src/main.zig b/src/main.zig index 1ac9680..5c414a8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,6 +1,7 @@ const std = @import("std"); const langs = @import("lang.zig"); const runners = @import("runner.zig"); +const printer = @import("printer.zig"); test "scritcher" { _ = @import("lang.zig"); @@ -52,6 +53,9 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // TODO save the line to scri_file? or should we have a special `push` // to do so? + + // note this is debug + try printer.printList(cmds, stdout); } } diff --git a/src/printer.zig b/src/printer.zig new file mode 100644 index 0000000..29aeb9b --- /dev/null +++ b/src/printer.zig @@ -0,0 +1,23 @@ +const langs = @import("lang.zig"); + +pub fn printList(list: langs.CommandList, stream: var) !void { + for (list.toSlice()) |cmd| { + var command = switch (cmd.command) { + .Noop => "noop", + .Load => "load", + .Quicksave => "quicksave", + .RunQS => "runqs", + + // TODO rest of commands + else => unreachable, + }; + + try stream.print("{}", command); + + for (cmd.args.toSlice()) |arg| { + try stream.print(" {}", arg); + } + + try stream.write(";\n"); + } +} From c90590e3b53f4953569dec8a128a02f4cd7c31b7 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 10 Sep 2019 12:12:10 -0300 Subject: [PATCH 05/11] add Lang.reset, open scri_file and write current commands to it --- src/lang.zig | 5 +++++ src/main.zig | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index fe31d11..9724dfb 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -158,6 +158,11 @@ pub const Lang = struct { self.keywords.deinit(); } + pub fn reset(self: *Lang) void { + self.has_error = false; + self.line = 0; + } + fn fillKeywords(self: *Lang) !void { _ = try self.keywords.put("noop", .Noop); _ = try self.keywords.put("load", .Load); diff --git a/src/main.zig b/src/main.zig index 5c414a8..c0af701 100644 --- a/src/main.zig +++ b/src/main.zig @@ -14,6 +14,12 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { 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. @@ -41,7 +47,7 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var buffer = try std.Buffer.init(allocator, ""[0..]); var line = std.io.readLine(&buffer) catch |err| { - if (err == error.EndOfStream) return; + if (err == error.EndOfStream) break; return err; }; @@ -51,11 +57,13 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { }; 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? - // note this is debug - try printer.printList(cmds, stdout); + try file.seekTo(0); + try printer.printList(cmds, stream); } } From 058bf8deb90c21c3d318df79af173a2b527de439 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 10 Sep 2019 14:51:41 -0300 Subject: [PATCH 06/11] add push and list commands --- src/main.zig | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main.zig b/src/main.zig index c0af701..1c7acaf 100644 --- a/src/main.zig +++ b/src/main.zig @@ -43,6 +43,7 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { defer lang.deinit(); while (true) { + lang.reset(); try stdout.print("> "); var buffer = try std.Buffer.init(allocator, ""[0..]); @@ -51,19 +52,20 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { return err; }; + if (std.mem.eql(u8, line, "push")) { + try file.seekTo(0); + try printer.printList(cmds, stream); + continue; + } else if (std.mem.eql(u8, line, "list")) { + try printer.printList(cmds, stream); + continue; + } + 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); } } From 88a73e64d81910a7ffb10c5be45f218041b18978 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 10 Sep 2019 15:44:10 -0300 Subject: [PATCH 07/11] better repl logic --- src/main.zig | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main.zig b/src/main.zig index 1c7acaf..671ed3f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -39,9 +39,15 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // TODO start a runner and keep it hot + // we keep + // - a CommandList with the full commands we have right now + // - a Command with the current last typed successful command + var lang = langs.Lang.init(allocator); defer lang.deinit(); + var current: langs.Command = undefined; + while (true) { lang.reset(); try stdout.print("> "); @@ -53,10 +59,13 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { }; if (std.mem.eql(u8, line, "push")) { - try file.seekTo(0); - try printer.printList(cmds, stream); + try cmds.append(current); continue; } else if (std.mem.eql(u8, line, "list")) { + try printer.printList(cmds, stdout); + continue; + } else if (std.mem.eql(u8, line, "save")) { + try file.seekTo(0); try printer.printList(cmds, stream); continue; } @@ -65,7 +74,7 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { std.debug.warn("repl: error while parsing: {}\n", err); continue; }; - try cmds.append(cmds_parsed.at(0)); + current = cmds_parsed.at(0); } } From 67c42e39d479811195e81265a938ad78d0d48989 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 10 Sep 2019 21:31:23 -0300 Subject: [PATCH 08/11] add cloning of Runner and Image + basic Runner REPL logic --- src/image.zig | 21 ++++++++++++++++++++- src/main.zig | 34 +++++++++++++++++++++++++++++----- src/runner.zig | 4 ++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/image.zig b/src/image.zig index 3e38903..1942f87 100644 --- a/src/image.zig +++ b/src/image.zig @@ -131,7 +131,6 @@ pub const Image = struct { /// Open a BMP image for later. pub fn open(allocator: *std.mem.Allocator, path: []const u8) !*Image { var in_fmt = mkSfInfo(); - var sndfile = try sopen(allocator, path, c.SFM_READ, &in_fmt); var image = try allocator.create(Image); @@ -149,6 +148,26 @@ pub const Image = struct { return image; } + pub fn clone(self: *Image) !*Image { + var in_fmt = mkSfInfo(); + // clone sndfile + var sndfile = try sopen(self.allocator, self.path, c.SFM_READ, &in_fmt); + var image = try allocator.create(Image); + + std.debug.assert(in_fmt.frames > i64(0)); + std.debug.assert(in_fmt.seekable == i32(1)); + + image.* = Image{ + .allocator = self.allocator, + .sndfile = sndfile, + .path = self.path, + .curpath = self.curpath, + .frames = @intCast(usize, in_fmt.frames), + }; + + return image; + } + pub fn close(self: *Image) void { //self.allocator.free(self.path); //self.allocator.free(self.curpath); diff --git a/src/main.zig b/src/main.zig index 671ed3f..be83ad6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -8,6 +8,13 @@ test "scritcher" { _ = @import("runner.zig"); } +fn wrapInCmdList(allocator: *std.mem.Allocator, cmd: langs.Command) !langs.CommandList { + var cmds = try langs.CommandList.init(allocator); + try cmds.append(cmd); + + return cmds; +} + pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var stdout_file = try std.io.getStdOut(); const stdout = &stdout_file.outStream().stream; @@ -24,30 +31,38 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // 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{ + var cmds = try wrapInCmdList(allocator, langs.Command{ .command = .Load, .args = loadargs, }); - // TODO start a runner and keep it hot + defer cmds.deinit(); // we keep // - a CommandList with the full commands we have right now // - a Command with the current last typed successful command + // - one runner that contains the current full state of the image + // as if the current cmds was ran over it (TODO better wording) + // - one runner that gets copied from the original on every new + // command the user issues + var lang = langs.Lang.init(allocator); defer lang.deinit(); var current: langs.Command = undefined; + var runner = runners.Runner.init(allocator); + defer runner.deinit(); + + // run the load command + try runner.runCommands(cmds, true); + while (true) { lang.reset(); try stdout.print("> "); @@ -60,6 +75,10 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { if (std.mem.eql(u8, line, "push")) { try cmds.append(current); + var cmds_wrapped = try wrapInCmdList(allocator, current); + defer cmds_wrapped.deinit(); + + try runner.runCommands(cmds_wrapped, true); continue; } else if (std.mem.eql(u8, line, "list")) { try printer.printList(cmds, stdout); @@ -75,6 +94,11 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { continue; }; current = cmds_parsed.at(0); + + var runner_clone = try runner.clone(); + defer runner_clone.deinit(); + + try runner_clone.runCommands(cmds_parsed, true); } } diff --git a/src/runner.zig b/src/runner.zig index a348f22..909a9b2 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -33,6 +33,10 @@ pub const Runner = struct { } } + pub fn clone(self: *Runner) *Runner { + return Runner{ .allocator = allocator, .image = try image.clone() }; + } + fn resolveArg(self: *Runner, load_path: []const u8) ![]const u8 { if (load_path[0] == ':') { // parse the index from 1 to end From 84d582cfd1c2a582cbad2800da5c0a1397899e04 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 10 Sep 2019 21:35:22 -0300 Subject: [PATCH 09/11] image: open curpath instead of path when cloning --- src/image.zig | 2 +- src/main.zig | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/image.zig b/src/image.zig index 1942f87..fdad5ca 100644 --- a/src/image.zig +++ b/src/image.zig @@ -151,7 +151,7 @@ pub const Image = struct { pub fn clone(self: *Image) !*Image { var in_fmt = mkSfInfo(); // clone sndfile - var sndfile = try sopen(self.allocator, self.path, c.SFM_READ, &in_fmt); + var sndfile = try sopen(self.allocator, self.curpath, c.SFM_READ, &in_fmt); var image = try allocator.create(Image); std.debug.assert(in_fmt.frames > i64(0)); diff --git a/src/main.zig b/src/main.zig index be83ad6..011256d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -75,10 +75,13 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { if (std.mem.eql(u8, line, "push")) { try cmds.append(current); + + // run the current added command to main cmds list + // with the main parent runner var cmds_wrapped = try wrapInCmdList(allocator, current); defer cmds_wrapped.deinit(); - try runner.runCommands(cmds_wrapped, true); + continue; } else if (std.mem.eql(u8, line, "list")) { try printer.printList(cmds, stdout); @@ -95,6 +98,9 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { }; current = cmds_parsed.at(0); + // by cloning the parent runner, we can iteratively write + // whatever command we want and only commit the good results + // back to the parent runner var runner_clone = try runner.clone(); defer runner_clone.deinit(); From 49cc7221b032c7b604bba300db3e9047e81495e0 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 10 Sep 2019 22:00:07 -0300 Subject: [PATCH 10/11] fix some clones, finish list of commands for printer --- src/image.zig | 2 +- src/main.zig | 15 ++++++++++++--- src/printer.zig | 20 ++++++++++++++++++-- src/runner.zig | 5 +++-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/image.zig b/src/image.zig index fdad5ca..0e9c775 100644 --- a/src/image.zig +++ b/src/image.zig @@ -152,7 +152,7 @@ pub const Image = struct { var in_fmt = mkSfInfo(); // clone sndfile var sndfile = try sopen(self.allocator, self.curpath, c.SFM_READ, &in_fmt); - var image = try allocator.create(Image); + var image = try self.allocator.create(Image); std.debug.assert(in_fmt.frames > i64(0)); std.debug.assert(in_fmt.seekable == i32(1)); diff --git a/src/main.zig b/src/main.zig index 011256d..be034f9 100644 --- a/src/main.zig +++ b/src/main.zig @@ -9,9 +9,8 @@ test "scritcher" { } fn wrapInCmdList(allocator: *std.mem.Allocator, cmd: langs.Command) !langs.CommandList { - var cmds = try langs.CommandList.init(allocator); + var cmds = langs.CommandList.init(allocator); try cmds.append(cmd); - return cmds; } @@ -33,7 +32,6 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var loadargs = langs.ArgList.init(allocator); defer loadargs.deinit(); - try loadargs.append(":1"); var cmds = try wrapInCmdList(allocator, langs.Command{ @@ -63,6 +61,12 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { // run the load command try runner.runCommands(cmds, true); + var runqs_args = langs.ArgList.init(allocator); + defer runqs_args.deinit(); + + // TODO change the runqs command to something given in an env var + try runqs_args.append("ristretto"); + while (true) { lang.reset(); try stdout.print("> "); @@ -104,6 +108,11 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var runner_clone = try runner.clone(); defer runner_clone.deinit(); + try cmds_parsed.append(langs.Command{ + .command = .RunQS, + .args = runqs_args, + }); + try runner_clone.runCommands(cmds_parsed, true); } } diff --git a/src/printer.zig b/src/printer.zig index 29aeb9b..2a30f8e 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -8,8 +8,24 @@ pub fn printList(list: langs.CommandList, stream: var) !void { .Quicksave => "quicksave", .RunQS => "runqs", - // TODO rest of commands - else => unreachable, + .Amp => "amp", + .RFlanger => "rflanger", + .Eq => "eq", + .Phaser => "phaser", + .Mbeq => "mbeq", + .Chorus => "chorus", + .PitchScaler => "pitchscaler", + .Reverb => "reverb", + .Highpass => "highpass", + .Delay => "delay", + .Vinyl => "vinyl", + .RevDelay => "revdelay", + + .Noise => "noise", + .WildNoise => "wildnoise", + .Write => "write", + + .Rotate => "rotate", }; try stream.print("{}", command); diff --git a/src/runner.zig b/src/runner.zig index 909a9b2..a010325 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -33,8 +33,9 @@ pub const Runner = struct { } } - pub fn clone(self: *Runner) *Runner { - return Runner{ .allocator = allocator, .image = try image.clone() }; + pub fn clone(self: *Runner) !Runner { + var cloned_image = if (self.image) |image| try image.clone() else null; + return Runner{ .allocator = self.allocator, .image = cloned_image }; } fn resolveArg(self: *Runner, load_path: []const u8) ![]const u8 { From 66a73565023498b2bae0d6920d3083fc311f25c0 Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 10 Sep 2019 22:08:35 -0300 Subject: [PATCH 11/11] runner: add newline to runqs message --- src/runner.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runner.zig b/src/runner.zig index a010325..072e38b 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -178,7 +178,7 @@ pub const Runner = struct { ); defer proc.deinit(); - std.debug.warn("running '{} {}'", program, out_path); + std.debug.warn("running '{} {}'\n", program, out_path); _ = try proc.spawnAndWait(); }