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");