aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/jq/execute.zig
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-01-28 22:45:29 +0900
committernsfisis <nsfisis@gmail.com>2026-01-28 22:45:29 +0900
commitfda13fefa083f9cc6489d55d21aab8ca0300e783 (patch)
treee4fcb14d3ed4e59db1fc4efb16801093c6deb31a /src/jq/execute.zig
parent9ddb831241a150e83fa18d1f681c264118c91fbc (diff)
downloadzgjq-fda13fefa083f9cc6489d55d21aab8ca0300e783.tar.gz
zgjq-fda13fefa083f9cc6489d55d21aab8ca0300e783.tar.zst
zgjq-fda13fefa083f9cc6489d55d21aab8ca0300e783.zip
implement array construction
Diffstat (limited to 'src/jq/execute.zig')
-rw-r--r--src/jq/execute.zig51
1 files changed, 42 insertions, 9 deletions
diff --git a/src/jq/execute.zig b/src/jq/execute.zig
index 282a35c..3775952 100644
--- a/src/jq/execute.zig
+++ b/src/jq/execute.zig
@@ -114,19 +114,37 @@ pub const Runtime = struct {
instrs: []const Instr,
pc: usize,
constants: std.ArrayList(jv.Value),
+ variables: std.ArrayList(jv.Value),
pub fn init(allocator: std.mem.Allocator) !Self {
+ // The order of this table must match with ConstIndex's order.
+ var constants = try std.ArrayList(jv.Value).initCapacity(allocator, 4);
+ try constants.append(allocator, .null);
+ try constants.append(allocator, .{ .bool = false });
+ try constants.append(allocator, .{ .bool = true });
+ try constants.append(allocator, .{ .array = jv.Array.init(allocator) });
+
return .{
.allocator = allocator,
.values = try ValueStack.init(allocator),
.forks = .{},
.instrs = &[_]Instr{},
.pc = 0,
- .constants = .{},
+ .constants = constants,
+ .variables = .{},
};
}
pub fn deinit(self: *Self) void {
+ for (self.variables.items) |*value| {
+ switch (value.*) {
+ .string => |s| self.allocator.free(s),
+ .array => |*a| a.deinit(),
+ .object => |*o| o.deinit(),
+ else => {},
+ }
+ }
+ self.variables.deinit(self.allocator);
for (self.constants.items) |*value| {
switch (value.*) {
.string => |s| self.allocator.free(s),
@@ -169,7 +187,7 @@ pub const Runtime = struct {
pub fn next(self: *Self) !?jv.Value {
std.debug.assert(self.instrs.len > 0);
- self.restore_stack();
+ _ = self.restore_stack();
while (self.pc < self.instrs.len) : (self.pc += 1) {
const cur = self.instrs[self.pc];
@@ -196,6 +214,11 @@ pub const Runtime = struct {
.fork => |offset| {
try self.save_stack(self.pc + offset);
},
+ .backtrack => {
+ if (self.restore_stack()) {
+ self.pc -= 1;
+ }
+ },
.dup => {
std.debug.assert(self.values.ensureSize(1));
@@ -337,17 +360,25 @@ pub const Runtime = struct {
_ = self.values.pop();
try self.values.push(self.constants.items[@intFromEnum(idx)]);
},
- .const_true => {
+ .load => |idx| {
+ try self.values.push(self.variables.items[@intFromEnum(idx)]);
+ },
+ .store => |idx| {
std.debug.assert(self.values.ensureSize(1));
- _ = self.values.pop();
- try self.values.push(.{ .bool = true });
+ // TODO: Allocate all local variables at startup.
+ while (self.variables.items.len <= @intFromEnum(idx)) {
+ try self.variables.append(self.allocator, .null);
+ }
+ self.variables.items[@intFromEnum(idx)] = self.values.pop();
},
- .const_false => {
+ .append => |idx| {
std.debug.assert(self.values.ensureSize(1));
- _ = self.values.pop();
- try self.values.push(.{ .bool = false });
+ switch (self.variables.items[@intFromEnum(idx)]) {
+ .array => |*a| try a.append(self.values.pop()),
+ else => unreachable,
+ }
},
}
}
@@ -360,10 +391,12 @@ pub const Runtime = struct {
try self.values.save();
}
- fn restore_stack(self: *Self) void {
+ fn restore_stack(self: *Self) bool {
if (self.forks.pop()) |target_pc| {
self.pc = target_pc;
self.values.restore();
+ return true;
}
+ return false;
}
};