aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/jq/execute.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/jq/execute.zig')
-rw-r--r--src/jq/execute.zig29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/jq/execute.zig b/src/jq/execute.zig
index 82b6557..6d4f194 100644
--- a/src/jq/execute.zig
+++ b/src/jq/execute.zig
@@ -110,6 +110,7 @@ pub const Runtime = struct {
allocator: std.mem.Allocator,
values: ValueStack,
+ forks: std.ArrayList(usize),
instrs: []const Instr,
pc: usize,
@@ -117,6 +118,7 @@ pub const Runtime = struct {
return .{
.allocator = allocator,
.values = try ValueStack.init(allocator),
+ .forks = .{},
.instrs = &[_]Instr{},
.pc = 0,
};
@@ -129,6 +131,7 @@ pub const Runtime = struct {
self.allocator.free(self.instrs);
self.values.deinit();
+ self.forks.deinit(self.allocator);
}
pub fn compileFromReader(self: *Self, reader: *std.Io.Reader) !void {
@@ -140,6 +143,11 @@ pub const Runtime = struct {
const ast = try parse(self.allocator, compile_allocator.allocator(), tokens);
const instrs = try compile(self.allocator, compile_allocator.allocator(), ast);
self.instrs = instrs;
+ // std.debug.print("BEGIN\n", .{});
+ // for (self.instrs) |instr| {
+ // std.debug.print("{}\n", .{instr});
+ // }
+ // std.debug.print("END\n", .{});
}
pub fn compileFromSlice(self: *Self, query: []const u8) !void {
@@ -154,14 +162,23 @@ pub const Runtime = struct {
pub fn next(self: *Self) !?jv.Value {
std.debug.assert(self.instrs.len > 0);
+ self.restore_stack();
+
while (self.pc < self.instrs.len) : (self.pc += 1) {
const cur = self.instrs[self.pc];
+ // std.debug.print("{}\n", .{cur});
switch (cur) {
.nop => {},
.ret => {
self.pc += 1;
return self.values.pop();
},
+ .jump => |offset| {
+ self.pc += offset - 1;
+ },
+ .fork => |offset| {
+ try self.save_stack(self.pc + offset);
+ },
.subexp_begin => try self.values.dup(),
.subexp_end => try self.values.swap(),
.array_index => {
@@ -199,4 +216,16 @@ pub const Runtime = struct {
return null;
}
+
+ fn save_stack(self: *Self, target_pc: usize) !void {
+ try self.forks.append(self.allocator, target_pc);
+ try self.values.save();
+ }
+
+ fn restore_stack(self: *Self) void {
+ if (self.forks.pop()) |target_pc| {
+ self.pc = target_pc;
+ self.values.restore();
+ }
+ }
};