aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/jq/codegen.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/jq/codegen.zig')
-rw-r--r--src/jq/codegen.zig39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/jq/codegen.zig b/src/jq/codegen.zig
index 23383bf..1fc889d 100644
--- a/src/jq/codegen.zig
+++ b/src/jq/codegen.zig
@@ -38,6 +38,22 @@ pub const Opcode = enum {
store,
append,
each,
+
+ pub fn name(self: Opcode) []const u8 {
+ switch (self) {
+ inline else => |tag| {
+ const tag_name = @tagName(tag);
+ const upper_tag_name = comptime blk: {
+ var buf: [tag_name.len]u8 = undefined;
+ for (tag_name, 0..) |c, i| {
+ buf[i] = std.ascii.toUpper(c);
+ }
+ break :blk buf;
+ };
+ return &upper_tag_name;
+ },
+ }
+ }
};
pub const Instr = union(Opcode) {
@@ -304,3 +320,26 @@ pub fn codegen(allocator: std.mem.Allocator, ast: *const Ast) ![]Instr {
try gen.emit(.ret);
return gen.toOwnedSlice();
}
+
+pub fn disasm(allocator: std.mem.Allocator, instrs: []const Instr, constants: []const jv.Value, writer: *std.Io.Writer) !void {
+ for (instrs, 0..) |instr, i| {
+ try writer.print("{d:0>4} ", .{i});
+ try writer.writeAll(instr.op().name());
+ switch (instr) {
+ // program address
+ .jump, .jump_unless, .fork => |offset| try writer.print(" {d:0>4}", .{i + offset}),
+ // constant index
+ .@"const" => |idx| {
+ try writer.writeAll(" ");
+ const k = try jv.stringify(allocator, constants[@intFromEnum(idx)]);
+ defer allocator.free(k);
+ try writer.writeAll(k);
+ },
+ // variable index
+ .load, .store, .append => |idx| try writer.print(" ${d}", .{@intFromEnum(idx)}),
+ // no arguments
+ else => {},
+ }
+ try writer.writeAll("\n");
+ }
+}