diff --git a/src/main.zig b/src/main.zig index 541ba53..a2716d7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -16,12 +16,26 @@ const readline = @cImport({ @cInclude("readline/history.h"); }); -fn wrapInCmdList(allocator: *std.mem.Allocator, cmd: langs.Command) !langs.CommandList { +fn wrapInCmdList(allocator: *std.mem.Allocator, cmd: *langs.Command) !langs.CommandList { var cmds = langs.CommandList.init(allocator); try cmds.append(cmd); return cmds; } +fn copyCommandToHeap(allocator: *std.mem.Allocator, command: langs.Command, comptime tag: langs.Command.Tag) !*langs.Command { + const CommandStruct = langs.Command.tagToType(tag); + const casted = command.cast(CommandStruct).?; + var heap_cmd = try allocator.create(CommandStruct); + + @memcpy( + @ptrCast([*]u8, &heap_cmd), + @ptrCast([*]const u8, &casted), + @sizeOf(CommandStruct), + ); + + return &heap_cmd.base; +} + pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var stdout_file = std.io.getStdOut(); const stdout = &stdout_file.outStream(); @@ -104,11 +118,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(); - const wanted_runner: []const u8 = std.os.getenv("SCRITCHER_RUNNER") orelse "ristretto"; - try runqs_args.append(wanted_runner); + + var runqs_cmd = langs.Command.RunQS{ + .base = langs.Command{ .tag = langs.Command.Tag.runqs }, + .program = wanted_runner, + }; while (true) { lang.reset(); @@ -124,11 +139,51 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { var line = rd_line[0..std.mem.len(rd_line)]; if (std.mem.eql(u8, line, "push")) { - try cmds.append(current); + const heap_cmd = switch (current.tag) { + .noop => try copyCommandToHeap(allocator, current, .noop), + .load => try copyCommandToHeap(allocator, current, .load), + .quicksave => try copyCommandToHeap(allocator, current, .quicksave), + .runqs => try copyCommandToHeap(allocator, current, .runqs), + .amp => try copyCommandToHeap(allocator, current, .amp), + .rflanger => try copyCommandToHeap(allocator, current, .rflanger), + .eq => try copyCommandToHeap(allocator, current, .eq), + .phaser => try copyCommandToHeap(allocator, current, .phaser), + .mbeq => try copyCommandToHeap(allocator, current, .mbeq), + .chorus => try copyCommandToHeap(allocator, current, .chorus), + .pitchscaler => try copyCommandToHeap(allocator, current, .pitchscaler), + .reverb => try copyCommandToHeap(allocator, current, .reverb), + .highpass => try copyCommandToHeap(allocator, current, .highpass), + .delay => try copyCommandToHeap(allocator, current, .delay), + .vinyl => try copyCommandToHeap(allocator, current, .vinyl), + .revdelay => try copyCommandToHeap(allocator, current, .revdelay), + .gate => try copyCommandToHeap(allocator, current, .gate), + .detune => try copyCommandToHeap(allocator, current, .detune), + .overdrive => try copyCommandToHeap(allocator, current, .overdrive), + .degrade => try copyCommandToHeap(allocator, current, .degrade), + .repsycho => try copyCommandToHeap(allocator, current, .repsycho), + .talkbox => try copyCommandToHeap(allocator, current, .talkbox), + .dyncomp => try copyCommandToHeap(allocator, current, .dyncomp), + .thruzero => try copyCommandToHeap(allocator, current, .thruzero), + .foverdrive => try copyCommandToHeap(allocator, current, .foverdrive), + .gverb => try copyCommandToHeap(allocator, current, .gverb), + .invert => try copyCommandToHeap(allocator, current, .invert), + .tapedelay => try copyCommandToHeap(allocator, current, .tapedelay), + .moddelay => try copyCommandToHeap(allocator, current, .moddelay), + .multichorus => try copyCommandToHeap(allocator, current, .multichorus), + .saturator => try copyCommandToHeap(allocator, current, .saturator), + .vintagedelay => try copyCommandToHeap(allocator, current, .vintagedelay), + .noise => try copyCommandToHeap(allocator, current, .noise), + .wildnoise => try copyCommandToHeap(allocator, current, .wildnoise), + .write => try copyCommandToHeap(allocator, current, .write), + .embed => try copyCommandToHeap(allocator, current, .embed), + .rotate => try copyCommandToHeap(allocator, current, .rotate), + }; + + try cmds.append(heap_cmd); // run the current added command to main cmds list // with the main parent runner - var cmds_wrapped = try wrapInCmdList(allocator, current); + var cmds_wrapped = try wrapInCmdList(allocator, heap_cmd); defer cmds_wrapped.deinit(); try runner.runCommands(cmds_wrapped, true); @@ -153,7 +208,7 @@ pub fn doRepl(allocator: *std.mem.Allocator, args_it: var) !void { std.debug.warn("repl: error while parsing: {}\n", .{err}); continue; }; - current = cmds_parsed.items[0]; + current = cmds_parsed.items[0].*; // by cloning the parent runner, we can iteratively write // whatever command we want and only commit the good results @@ -161,10 +216,9 @@ 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, - }); + // taking address is fine, because runqs_cmd lives in the lifetime + // of this function. + try cmds.append(&runqs_cmd.base); try runner_clone.runCommands(cmds_parsed, true); _ = try stdout.write("\n"); diff --git a/src/printer.zig b/src/printer.zig index 3efdde7..2302cfc 100644 --- a/src/printer.zig +++ b/src/printer.zig @@ -1,6 +1,18 @@ +const std = @import("std"); const langs = @import("lang.zig"); -pub fn printCommand(cmd: langs.Command, comptime tag: langs.Command.Tag) !void { +fn printCommandWithParams(stream: var, command: var) !void { + const Parameters = @TypeOf(command.parameters); + inline for (@typeInfo(Parameters).Struct.fields) |field| { + if (field.field_type == f32 or field.field_type == f64) { + try stream.print(" {d}", .{@field(command.parameters, field.name)}); + } else { + try stream.print(" {}", .{@field(command.parameters, field.name)}); + } + } +} + +fn printCommand(stream: var, cmd: *langs.Command, comptime tag: langs.Command.Tag) !void { const CommandStruct = langs.Command.tagToType(tag); const casted = cmd.cast(CommandStruct).?; @@ -10,10 +22,10 @@ pub fn printCommand(cmd: langs.Command, comptime tag: langs.Command.Tag) !void { else => true, }; - const ctype = typ.command_type; + const ctype = CommandStruct.command_type; switch (ctype) { - .lv2_command => try printLV2Command(casted), - .custom_command => try printCustomCommand(casted), + .lv2_command => try printCommandWithParams(stream, casted), + .custom_command => try printCommandWithParams(stream, casted), else => @panic("TODO support command type"), } } @@ -25,48 +37,52 @@ pub fn printList(list: langs.CommandList, stream: var) !void { switch (cmd.tag) { .load => { - const load = command.cast(langs.Command.Load).?; - try stream.print("{}", .{load.path}); + const load = cmd.cast(langs.Command.Load).?; + try stream.print(" {}", .{load.path}); }, - .quicksave => {}, + .runqs => { + const runqs = cmd.cast(langs.Command.RunQS).?; + try stream.print(" {}", .{runqs.program}); + }, + .noop, .quicksave => {}, .rotate => { - const rotate = command.cast(langs.Command.Rotate).?; - try stream.print("{} {}", .{ rotate.deg, rotate.bgfill }); + const rotate = cmd.cast(langs.Command.Rotate).?; + try stream.print(" {d} {}", .{ rotate.deg, rotate.bgfill }); }, - .amp => try printCommand(cmd, .amp), - .rflanger => try printCommand(cmd, .rflanger), - .eq => try printCommand(cmd, .eq), - .phaser => try printCommand(cmd, .phaser), - .mbeq => try printCommand(cmd, .mbeq), - .chorus => try printCommand(cmd, .chorus), - .pitchscaler => try printCommand(cmd, .pitchscaler), - .reverb => try printCommand(cmd, .reverb), - .highpass => try printCommand(cmd, .highpass), - .delay => try printCommand(cmd, .delay), - .vinyl => try printCommand(cmd, .vinyl), - .revdelay => try printCommand(cmd, .revdelay), - .gate => try printCommand(cmd, .gate), - .detune => try printCommand(cmd, .detune), - .overdrive => try printCommand(cmd, .overdrive), - .degrade => try printCommand(cmd, .degrade), - .repsycho => try printCommand(cmd, .repsycho), - .talkbox => try printCommand(cmd, .talkbox), - .dyncomp => try printCommand(cmd, .dyncomp), - .thruzero => try printCommand(cmd, .thruzero), - .foverdrive => try printCommand(cmd, .foverdrive), - .gverb => try printCommand(cmd, .gverb), - .invert => try printCommand(cmd, .invert), - .tapedelay => try printCommand(cmd, .tapedelay), - .moddelay => try printCommand(cmd, .moddelay), - .multichorus => try printCommand(cmd, .multichorus), - .saturator => try printCommand(cmd, .saturator), - .vintagedelay => try printCommand(cmd, .vintagedelay), + .amp => try printCommand(stream, cmd, .amp), + .rflanger => try printCommand(stream, cmd, .rflanger), + .eq => try printCommand(stream, cmd, .eq), + .phaser => try printCommand(stream, cmd, .phaser), + .mbeq => try printCommand(stream, cmd, .mbeq), + .chorus => try printCommand(stream, cmd, .chorus), + .pitchscaler => try printCommand(stream, cmd, .pitchscaler), + .reverb => try printCommand(stream, cmd, .reverb), + .highpass => try printCommand(stream, cmd, .highpass), + .delay => try printCommand(stream, cmd, .delay), + .vinyl => try printCommand(stream, cmd, .vinyl), + .revdelay => try printCommand(stream, cmd, .revdelay), + .gate => try printCommand(stream, cmd, .gate), + .detune => try printCommand(stream, cmd, .detune), + .overdrive => try printCommand(stream, cmd, .overdrive), + .degrade => try printCommand(stream, cmd, .degrade), + .repsycho => try printCommand(stream, cmd, .repsycho), + .talkbox => try printCommand(stream, cmd, .talkbox), + .dyncomp => try printCommand(stream, cmd, .dyncomp), + .thruzero => try printCommand(stream, cmd, .thruzero), + .foverdrive => try printCommand(stream, cmd, .foverdrive), + .gverb => try printCommand(stream, cmd, .gverb), + .invert => try printCommand(stream, cmd, .invert), + .tapedelay => try printCommand(stream, cmd, .tapedelay), + .moddelay => try printCommand(stream, cmd, .moddelay), + .multichorus => try printCommand(stream, cmd, .multichorus), + .saturator => try printCommand(stream, cmd, .saturator), + .vintagedelay => try printCommand(stream, cmd, .vintagedelay), - .noise => try printCommand(cmd, .noise), - .wildnoise => try printCommand(cmd, .wildnoise), - .write => try printCommand(cmd, .write), - .embed => try printCommand(cmd, .embed), + .noise => try printCommand(stream, cmd, .noise), + .wildnoise => try printCommand(stream, cmd, .wildnoise), + .write => try printCommand(stream, cmd, .write), + .embed => try printCommand(stream, cmd, .embed), } _ = try stream.write(";\n"); diff --git a/src/runner.zig b/src/runner.zig index 036975d..6b9f478 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -175,18 +175,19 @@ pub const Runner = struct { try image.saveTo(out_path); } - fn runQSCmd(self: *Runner, program: []const u8) !void { + fn runQSCmd(self: *Runner, cmd: lang.Command) !void { + const runqs = cmd.cast(lang.Command.RunQS).?; var image = try self.getImage(); const out_path = try self.makeGlitchedPath(); try image.saveTo(out_path); var proc = try std.ChildProcess.init( - &[_][]const u8{ program, out_path }, + &[_][]const u8{ runqs.program, out_path }, self.allocator, ); defer proc.deinit(); - std.debug.warn("running '{} {}'\n", .{ program, out_path }); + std.debug.warn("running '{} {}'\n", .{ runqs.program, out_path }); _ = try proc.spawnAndWait(); } @@ -249,12 +250,14 @@ pub const Runner = struct { fn runCommand(self: *@This(), cmd: lang.Command) !void { switch (cmd.tag) { + .noop => {}, .load => { const command = cmd.cast(lang.Command.Load).?; try self.loadCmd(command.path); }, .quicksave => try self.quicksaveCmd(), .rotate => try self.rotateCmd(cmd), + .runqs => try self.runQSCmd(cmd), .amp => try self.runSingleCommand(cmd, .amp), .rflanger => try self.runSingleCommand(cmd, .rflanger),