diff options
| -rw-r--r-- | src/jq/codegen.zig | 3 | ||||
| -rw-r--r-- | src/jq/execute.zig | 13 | ||||
| -rw-r--r-- | src/root.zig | 21 |
3 files changed, 37 insertions, 0 deletions
diff --git a/src/jq/codegen.zig b/src/jq/codegen.zig index e377a5c..21c5832 100644 --- a/src/jq/codegen.zig +++ b/src/jq/codegen.zig @@ -28,6 +28,7 @@ pub const Opcode = enum { gt, le, ge, + alt, @"const", const_true, const_false, @@ -58,6 +59,7 @@ pub const Instr = union(Opcode) { gt, le, ge, + alt, @"const": ConstIndex, const_true, const_false, @@ -108,6 +110,7 @@ const Codegen = struct { .gt => .gt, .le => .le, .ge => .ge, + .alt => .alt, else => return error.Unimplemented, }; try self.emit(op_instr); diff --git a/src/jq/execute.zig b/src/jq/execute.zig index f2bfe8c..0565004 100644 --- a/src/jq/execute.zig +++ b/src/jq/execute.zig @@ -328,6 +328,19 @@ pub const Runtime = struct { const result = try jv.ops.compare(lhs, rhs, .ge); try self.values.push(.{ .bool = result }); }, + .alt => { + std.debug.assert(self.values.ensureSize(3)); + + _ = self.values.pop(); + const lhs = self.values.pop(); + const rhs = self.values.pop(); + const is_falsy = switch (lhs) { + .null => true, + .bool => |b| !b, + else => false, + }; + try self.values.push(if (is_falsy) rhs else lhs); + }, .@"const" => |idx| { std.debug.assert(self.values.ensureSize(1)); diff --git a/src/root.zig b/src/root.zig index b612d89..7aee514 100644 --- a/src/root.zig +++ b/src/root.zig @@ -254,3 +254,24 @@ test "or operator" { try testRun("true", "{\"a\":false,\"b\":true}", ".a or .b"); try testRun("false", "{\"a\":false,\"b\":false}", ".a or .b"); } + +test "alternative operator" { + try testRun("\"default\"", "null", ". // \"default\""); + try testRun("\"hello\"", "\"hello\"", ". // \"default\""); + + try testRun("\"default\"", "false", ". // \"default\""); + try testRun("true", "true", ". // \"default\""); + + try testRun("123", "{\"a\":123}", ".a // \"default\""); + try testRun("\"default\"", "{\"a\":123}", ".b // \"default\""); + try testRun("\"default\"", "{\"a\":null}", ".a // \"default\""); + + try testRun("\"third\"", "null", "null // false // \"third\""); + try testRun("\"first\"", "null", "\"first\" // \"second\" // \"third\""); + + try testRun("0", "0", ". // 42"); + try testRun("\"\"", "\"\"", ". // \"default\""); + + try testRun("[]", "[]", ". // \"default\""); + try testRun("{}", "{}", ". // \"default\""); +} |
