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.zig59
1 files changed, 42 insertions, 17 deletions
diff --git a/src/jq/codegen.zig b/src/jq/codegen.zig
index 21c5832..6ca5382 100644
--- a/src/jq/codegen.zig
+++ b/src/jq/codegen.zig
@@ -1,9 +1,10 @@
const std = @import("std");
const jv = @import("../jv.zig");
+const ConstIndex = @import("./constant_table.zig").ConstIndex;
const Ast = @import("./parse.zig").Ast;
const BinaryOp = @import("./parse.zig").BinaryOp;
-pub const ConstIndex = enum(u32) { _ };
+pub const VariableIndex = enum(u32) { _ };
pub const Opcode = enum {
nop,
@@ -11,6 +12,7 @@ pub const Opcode = enum {
jump,
jump_unless,
fork,
+ backtrack,
dup,
pop,
subexp_begin,
@@ -30,8 +32,9 @@ pub const Opcode = enum {
ge,
alt,
@"const",
- const_true,
- const_false,
+ load,
+ store,
+ append,
};
pub const Instr = union(Opcode) {
@@ -42,6 +45,7 @@ pub const Instr = union(Opcode) {
jump: usize,
jump_unless: usize,
fork: usize,
+ backtrack,
dup,
pop,
subexp_begin,
@@ -61,8 +65,9 @@ pub const Instr = union(Opcode) {
ge,
alt,
@"const": ConstIndex,
- const_true,
- const_false,
+ load: VariableIndex,
+ store: VariableIndex,
+ append: VariableIndex,
pub fn op(self: Self) Opcode {
return self;
@@ -72,11 +77,13 @@ pub const Instr = union(Opcode) {
const Codegen = struct {
instrs: std.ArrayList(Instr),
allocator: std.mem.Allocator,
+ variables_count: usize,
fn init(allocator: std.mem.Allocator) !Codegen {
return .{
.instrs = try std.ArrayList(Instr).initCapacity(allocator, 16),
.allocator = allocator,
+ .variables_count = 0,
};
}
@@ -122,12 +129,12 @@ const Codegen = struct {
// POP
// <rhs>
// JUMP_UNLESS l1
- // CONST_TRUE
+ // CONST true
// JUMP l2
- // l1: CONST_FALSE
+ // l1: CONST false
// l2: JUMP l4
// l3: POP
- // CONST_FALSE
+ // CONST false
// l4:
try self.emit(.dup);
try self.generate(and_expr.lhs);
@@ -137,17 +144,17 @@ const Codegen = struct {
try self.generate(and_expr.rhs);
const jump2_idx = self.pos();
try self.emit(.{ .jump_unless = 0 });
- try self.emit(.const_true);
+ try self.emit(.{ .@"const" = .true });
const jump3_idx = self.pos();
try self.emit(.{ .jump = 0 });
const l1 = self.pos();
- try self.emit(.const_false);
+ try self.emit(.{ .@"const" = .false });
const jump4_idx = self.pos();
const l2 = self.pos();
try self.emit(.{ .jump = 0 });
const l3 = self.pos();
try self.emit(.pop);
- try self.emit(.const_false);
+ try self.emit(.{ .@"const" = .false });
const l4 = self.pos();
self.patchLabel(jump1_idx, l3);
@@ -160,21 +167,21 @@ const Codegen = struct {
// <lhs>
// JUMP_UNLESS l1
// POP
- // CONST_TRUE
+ // CONST true
// JUMP l3
// l1: POP
// <rhs>
// JUMP_UNLESS l2
- // CONST_TRUE
+ // CONST true
// JUMP l3
- // l2: CONST_FALSE
+ // l2: CONST false
// l3:
try self.emit(.dup);
try self.generate(or_expr.lhs);
const jump1_idx = self.pos();
try self.emit(.{ .jump_unless = 0 });
try self.emit(.pop);
- try self.emit(.const_true);
+ try self.emit(.{ .@"const" = .true });
const jump2_idx = self.pos();
try self.emit(.{ .jump = 0 });
const l1 = self.pos();
@@ -182,11 +189,11 @@ const Codegen = struct {
try self.generate(or_expr.rhs);
const jump3_idx = self.pos();
try self.emit(.{ .jump_unless = 0 });
- try self.emit(.const_true);
+ try self.emit(.{ .@"const" = .true });
const jump4_idx = self.pos();
try self.emit(.{ .jump = 0 });
const l2 = self.pos();
- try self.emit(.const_false);
+ try self.emit(.{ .@"const" = .false });
const l3 = self.pos();
self.patchLabel(jump1_idx, l1);
@@ -215,6 +222,24 @@ const Codegen = struct {
self.patchLabel(fork_index, l1);
self.patchLabel(jump_index, l2);
},
+ .construct_array => |arr| {
+ // DUP
+ // CONST []
+ // STORE v
+ // <items>
+ // APPEND v
+ // BACKTRACK
+ // LOAD v
+ const v: VariableIndex = @enumFromInt(self.variables_count);
+ self.variables_count += 1;
+ try self.emit(.dup);
+ try self.emit(.{ .@"const" = .empty_array });
+ try self.emit(.{ .store = v });
+ try self.generate(arr.items);
+ try self.emit(.{ .append = v });
+ try self.emit(.backtrack);
+ try self.emit(.{ .load = v });
+ },
}
}