chunk.zig (3041B)
1 const std = @import("std"); 2 const value = @import("value.zig"); 3 4 pub const Op = union(enum) { 5 // Finish execution of current function 6 @"return", 7 8 // Set current pc to this if the condition is false 9 jumpfalse: u32, 10 11 // Jump absolute to the target 12 jump: u32, 13 14 // ..[a] -> .. 15 pop, 16 17 // .. -> ..[c] 18 @"constant": u32, 19 20 // ..[v].. -> ..[v]..[v] 21 @"local": u32, 22 23 // .. -> ..[g] 24 get_global: u32, 25 26 // ..[g] -> .. 27 define_global: u32, 28 29 // ..[scope...][top...] -> ..[top...] 30 popscope: struct { 31 offset: u16, 32 scope: u16 33 }, 34 35 // ..[a] -> ..[-a] 36 negate, 37 38 // ..[args..] -> ..[ret] 39 call: usize, 40 41 // ..[r][l] -> ..[l op r] 42 add, 43 substract, 44 multiply, 45 pow, 46 47 // ..[r][l] -> ..[l cmp r] 48 compare: std.math.CompareOperator, 49 50 // ..[v] -> ..[v] 51 print, 52 53 // ..[r][l] -> ..[l/r][l%r] 54 div, 55 56 // ..[(lst.. )][h] -> ..[(h lst..)] 57 cons, 58 59 // ..[(h lst..)] -> ..[(lst..)][h] 60 uncons, 61 }; 62 63 var _ = std.debug.assert(@sizeOf(Op) == 4); 64 65 pub const Chunk = struct { 66 const Self = @This(); 67 68 const Instrs = std.ArrayList(Op); 69 const Values = std.ArrayList(*value.Value); 70 71 instrs: Instrs, 72 values: Values, 73 74 pub fn init(all: std.mem.Allocator) Self { 75 return Self { 76 .instrs = Instrs.init(all), 77 .values = Values.init(all) 78 }; 79 } 80 81 pub fn deinit(self: *Self) void { 82 self.instrs.deinit(); 83 84 for (self.values.items) |val| { 85 val.unref(); 86 } 87 88 self.values.deinit(); 89 } 90 91 pub fn write(self: *Self, instr: Op) !void { 92 try self.instrs.append(instr); 93 } 94 95 pub fn addConstant(self: *Self, val: *value.Value) !u32 { 96 try self.values.append(val); 97 return @intCast(self.values.items.len - 1); 98 } 99 100 pub fn disassembleInstr(self: Self, instr: Op) void { 101 std.debug.print("{s} ", .{@tagName(instr)}); 102 switch (instr) { 103 inline .@"constant", .get_global, .define_global => |vindex| { 104 const num = self.values.items[vindex]; 105 std.debug.print("{}", .{num.formatter()}); 106 }, 107 108 inline .call, .compare => |cval| { 109 std.debug.print("{}", .{cval}); 110 }, 111 112 inline .@"local", .jumpfalse, .jump => |vindex| { 113 std.debug.print("{}", .{vindex}); 114 }, 115 116 .popscope => |params| { 117 std.debug.print("offset={} scope={}", .{params.offset, params.scope}); 118 }, 119 120 inline else => {}, 121 } 122 std.debug.print("\n", .{}); 123 } 124 125 pub fn disassemble(self: Self) void { 126 for (self.instrs.items, 0..) |instr, pc| { 127 std.debug.print("{:04} |\t", .{pc}); 128 self.disassembleInstr(instr); 129 } 130 } 131 132 pub fn lastInstrRef(self: *Self) usize { 133 return self.instrs.items.len - 1; 134 } 135 136 pub fn nextPc(self: *const Self) u32 { 137 return @intCast(self.instrs.items.len); 138 } 139 }; 140