diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-01-25 16:14:57 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-01-25 16:14:57 +0900 |
| commit | 3e78bb75c4b431b0a4d07892aba6a64f11da2210 (patch) | |
| tree | b7a8d2a5412c75cd3ace1032db38e6535d3d0a1d | |
| parent | 448c28d596184f39783f8a7813ae73901fce240a (diff) | |
| download | zgjq-3e78bb75c4b431b0a4d07892aba6a64f11da2210.tar.gz zgjq-3e78bb75c4b431b0a4d07892aba6a64f11da2210.tar.zst zgjq-3e78bb75c4b431b0a4d07892aba6a64f11da2210.zip | |
implement arithmetic operations
| -rw-r--r-- | docs/jq_grammar.md | 12 | ||||
| -rw-r--r-- | src/jq/compile.zig | 19 | ||||
| -rw-r--r-- | src/jq/execute.zig | 36 | ||||
| -rw-r--r-- | src/root.zig | 22 |
4 files changed, 75 insertions, 14 deletions
diff --git a/docs/jq_grammar.md b/docs/jq_grammar.md index dc7cedb..339fac8 100644 --- a/docs/jq_grammar.md +++ b/docs/jq_grammar.md @@ -117,25 +117,14 @@ term: '.' '..' 'break' BINDING - term FIELD '?' - FIELD '?' - term '.' STRING '?' - '.' STRING '?' term FIELD FIELD term '.' STRING '.' STRING - term '[' query ']' '?' term '[' query ']' - term '.' '[' query ']' '?' term '.' '[' query ']' - term '[' ']' '?' term '[' ']' - term '.' '[' ']' '?' term '.' '[' ']' - term '[' query ':' query ']' '?' - term '[' query ':' ']' '?' - term '[' ':' query ']' '?' term '[' query ':' query ']' term '[' query ':' ']' term '[' ':' query ']' @@ -154,7 +143,6 @@ term: 'if' query 'then' query else-body 'try' expr 'catch' expr 'try' expr - '$' '$' '$' BINDING BINDING '$__loc__' IDENT diff --git a/src/jq/compile.zig b/src/jq/compile.zig index 40459c0..bb3a832 100644 --- a/src/jq/compile.zig +++ b/src/jq/compile.zig @@ -1,6 +1,7 @@ const std = @import("std"); const jv = @import("../jv.zig"); const Ast = @import("./parse.zig").Ast; +const BinaryOp = @import("./parse.zig").BinaryOp; pub const Opcode = enum { nop, @@ -11,6 +12,10 @@ pub const Opcode = enum { subexp_end, array_index, add, + sub, + mul, + div, + mod, object_key, literal, }; @@ -26,6 +31,10 @@ pub const Instr = union(Opcode) { subexp_end, array_index, add, + sub, + mul, + div, + mod, object_key: []const u8, literal: *jv.Value, @@ -68,7 +77,15 @@ fn compileExpr(allocator: std.mem.Allocator, compile_allocator: std.mem.Allocato try instrs.append(allocator, .subexp_begin); try instrs.appendSlice(allocator, lhs_instrs); try instrs.append(allocator, .subexp_end); - try instrs.append(allocator, .add); + const op_instr: Instr = switch (binary_expr.op) { + .add => .add, + .sub => .sub, + .mul => .mul, + .div => .div, + .mod => .mod, + else => return error.Unimplemented, + }; + try instrs.append(allocator, op_instr); }, .pipe => |pipe_expr| { const lhs_instrs = try compileExpr(allocator, compile_allocator, pipe_expr.lhs); diff --git a/src/jq/execute.zig b/src/jq/execute.zig index 6d4f194..3c83d23 100644 --- a/src/jq/execute.zig +++ b/src/jq/execute.zig @@ -198,6 +198,42 @@ pub const Runtime = struct { const result = lhs + rhs; try self.values.push(.{ .integer = result }); }, + .sub => { + std.debug.assert(self.values.ensureSize(3)); + + _ = self.values.pop(); + const lhs = try self.values.popInteger(); + const rhs = try self.values.popInteger(); + const result = lhs - rhs; + try self.values.push(.{ .integer = result }); + }, + .mul => { + std.debug.assert(self.values.ensureSize(3)); + + _ = self.values.pop(); + const lhs = try self.values.popInteger(); + const rhs = try self.values.popInteger(); + const result = lhs * rhs; + try self.values.push(.{ .integer = result }); + }, + .div => { + std.debug.assert(self.values.ensureSize(3)); + + _ = self.values.pop(); + const lhs = try self.values.popInteger(); + const rhs = try self.values.popInteger(); + const result = @divTrunc(lhs, rhs); + try self.values.push(.{ .integer = result }); + }, + .mod => { + std.debug.assert(self.values.ensureSize(3)); + + _ = self.values.pop(); + const lhs = try self.values.popInteger(); + const rhs = try self.values.popInteger(); + const result = @mod(lhs, rhs); + try self.values.push(.{ .integer = result }); + }, .object_key => |key| { std.debug.assert(self.values.ensureSize(1)); diff --git a/src/root.zig b/src/root.zig index 0d2a3ce..782f078 100644 --- a/src/root.zig +++ b/src/root.zig @@ -76,11 +76,31 @@ test "object key filter" { try testRun("{\"bar\":true}", "{\"foo\":{\"bar\":true}}", ".foo"); } -test "addition" { +test "arithmetic operations" { try testRun("579", "null", "123 + 456"); try testRun("35", "{\"a\":12,\"b\":23}", ".a + .b"); try testRun("12", "[1,2,3]", ".[1] + 10"); try testRun("6", "null", "1 + 2 + 3"); + + try testRun("333", "null", "456 - 123"); + try testRun("-11", "{\"a\":12,\"b\":23}", ".a - .b"); + try testRun("-8", "[1,2,3]", ".[1] - 10"); + try testRun("-4", "null", "1 - 2 - 3"); + + try testRun("56088", "null", "123 * 456"); + try testRun("276", "{\"a\":12,\"b\":23}", ".a * .b"); + try testRun("20", "[1,2,3]", ".[1] * 10"); + try testRun("6", "null", "1 * 2 * 3"); + + try testRun("3", "null", "456 / 123"); + try testRun("0", "{\"a\":12,\"b\":23}", ".a / .b"); + try testRun("5", "[10,20,30]", ".[1] / 4"); + try testRun("2", "null", "12 / 2 / 3"); + + try testRun("87", "null", "456 % 123"); + try testRun("12", "{\"a\":12,\"b\":23}", ".a % .b"); + try testRun("0", "[1,2,3]", ".[1] % 2"); + try testRun("0", "null", "12 % 2 % 3"); } test "pipe operator" { |
