DzLox

:)
git clone https://git.sr.ht/~ashymad/DzLox
Log | Files | Refs | Submodules | LICENSE

debug.zig (6261B)


      1 const std = @import("std");
      2 
      3 const value = @import("value.zig");
      4 
      5 const Obj = @import("gc.zig").GC.Obj;
      6 const Error = Obj.Error;
      7 const OP = @import("op.zig").OP;
      8 const Compiler = @import("vm.zig").VM.Compiler;
      9 const print = std.debug.print;
     10 
     11 pub fn disassembleChunk(ch: *const Obj.Chunk) Error!void {
     12     print("/=======\\\n", .{});
     13 
     14     var offset: usize = 0;
     15 
     16     while (offset < ch.code.ptr().len) {
     17         offset = try _disassembleInstruction(ch, offset, true);
     18     }
     19     print("\\=======/\n", .{});
     20 }
     21 
     22 pub fn print_offset(ch: *const Obj.Chunk, offset: usize) !void {
     23     print("{d:0>4} ", .{offset});
     24     const line = ch.lines.ptr().get(offset).?;
     25     if (offset > 0 and line == ch.lines.ptr().get(offset - 1).?) {
     26         print("   | ", .{});
     27     } else {
     28         print("{d:4} ", .{line});
     29     }
     30 }
     31 
     32 pub fn disassembleInstruction(ch: *const Obj.Chunk, offset: usize) Error!usize {
     33     return _disassembleInstruction(ch, offset, false);
     34 }
     35 
     36 fn _disassembleInstruction(ch: *const Obj.Chunk, offset: usize, print_fn: bool) Error!usize {
     37     try print_offset(ch, offset);
     38 
     39     const op = ch.code.ptr().get(offset).?;
     40     const name = @tagName(@as(OP, @enumFromInt(op)));
     41 
     42     return switch (op) {
     43         @intFromEnum(OP.RETURN) => simpleInstruction(name, offset),
     44         @intFromEnum(OP.NEGATE) => simpleInstruction(name, offset),
     45         @intFromEnum(OP.ADD) => simpleInstruction(name, offset),
     46         @intFromEnum(OP.SUBTRACT) => simpleInstruction(name, offset),
     47         @intFromEnum(OP.DIVIDE) => simpleInstruction(name, offset),
     48         @intFromEnum(OP.MULTIPLY) => simpleInstruction(name, offset),
     49         @intFromEnum(OP.TRUE) => simpleInstruction(name, offset),
     50         @intFromEnum(OP.FALSE) => simpleInstruction(name, offset),
     51         @intFromEnum(OP.EQUAL) => simpleInstruction(name, offset),
     52         @intFromEnum(OP.LESS) => simpleInstruction(name, offset),
     53         @intFromEnum(OP.GREATER) => simpleInstruction(name, offset),
     54         @intFromEnum(OP.NIL) => simpleInstruction(name, offset),
     55         @intFromEnum(OP.NOT) => simpleInstruction(name, offset),
     56         @intFromEnum(OP.CONSTANT) => try constantInstruction(name, ch, offset, print_fn),
     57         @intFromEnum(OP.DEFINE_GLOBAL) => try constantInstruction(name, ch, offset, print_fn),
     58         @intFromEnum(OP.METHOD) => try constantInstruction(name, ch, offset, print_fn) + 1,
     59         @intFromEnum(OP.DEFINE_GLOBAL_CONSTANT) => try constantInstruction(name, ch, offset, print_fn),
     60         @intFromEnum(OP.GET_GLOBAL) => try constantInstruction(name, ch, offset, print_fn),
     61         @intFromEnum(OP.SET_GLOBAL) => try constantInstruction(name, ch, offset, print_fn),
     62         @intFromEnum(OP.PRINT) => simpleInstruction(name, offset),
     63         @intFromEnum(OP.POP) => simpleInstruction(name, offset),
     64         @intFromEnum(OP.GET_LOCAL) => try byteInstruction(name, ch, offset),
     65         @intFromEnum(OP.SET_LOCAL) => try byteInstruction(name, ch, offset),
     66         @intFromEnum(OP.GET_UPVALUE) => try byteInstruction(name, ch, offset),
     67         @intFromEnum(OP.SET_UPVALUE) => try byteInstruction(name, ch, offset),
     68         @intFromEnum(OP.GET_PROPERTY) => try byteInstruction(name, ch, offset),
     69         @intFromEnum(OP.SET_PROPERTY) => try byteInstruction(name, ch, offset),
     70         @intFromEnum(OP.GET_SUPER) => try constantInstruction(name, ch, offset, print_fn),
     71         @intFromEnum(OP.JUMP_IF_FALSE) => try jumpInstruction(name, true, ch, offset),
     72         @intFromEnum(OP.JUMP_POP) => simpleInstruction(name, offset),
     73         @intFromEnum(OP.JUMP) => try jumpInstruction(name, true, ch, offset),
     74         @intFromEnum(OP.LOOP) => try jumpInstruction(name, false, ch, offset),
     75         @intFromEnum(OP.SET_INDEX) => simpleInstruction(name, offset),
     76         @intFromEnum(OP.GET_INDEX) => simpleInstruction(name, offset),
     77         @intFromEnum(OP.CALL) => try byteInstruction(name, ch, offset),
     78         @intFromEnum(OP.CLOSURE) => try closureInstruction(name, ch, offset),
     79         @intFromEnum(OP.CLOSE_UPVALUE) => simpleInstruction(name, offset),
     80         @intFromEnum(OP.INHERIT) => simpleInstruction(name, offset),
     81         else => blk: {
     82             print("Unknown opcode {d} {s}\n", .{ op, name });
     83             break :blk offset + 1;
     84         },
     85     };
     86 }
     87 
     88 fn simpleInstruction(name: []const u8, offset: usize) usize {
     89     print("{s}\n", .{name});
     90     return offset + 1;
     91 }
     92 
     93 fn constantInstruction(name: []const u8, ch: *const Obj.Chunk, offset: usize, print_fn: bool) Error!usize {
     94     const constant = ch.code.ptr().get(offset + 1).?;
     95     const constval = ch.constants.ptr().get(constant).?;
     96     print("{s:<32} {d:4} '{f}'\n", .{ name, constant, constval });
     97     if (print_fn) {
     98         if (constval.cast_if(Obj.Type.Function)) |function| {
     99             try disassembleChunk(function.chunk.ptr());
    100         } else if (constval.cast_if(Obj.Type.Chunk)) |chunk| {
    101             try disassembleChunk(chunk);
    102         }
    103     }
    104     return offset + 2;
    105 }
    106 
    107 fn byteInstruction(name: []const u8, ch: *const Obj.Chunk, offset: usize) Error!usize {
    108     print("{s:<32} {d:4}\n", .{ name, ch.code.ptr().get(offset + 1).? });
    109     return offset + 2;
    110 }
    111 
    112 fn jumpInstruction(name: []const u8, sign: bool, ch: *const Obj.Chunk, offset: usize) !usize {
    113     const msb: u16 = ch.code.ptr().get(offset + 1).?;
    114     const lsb: u16 = ch.code.ptr().get(offset + 2).?;
    115     const jump = (msb << 8) | lsb;
    116 
    117     print("{s:<32} {d:4} -> {d}\n", .{ name, offset, if (sign) offset + 3 + jump else offset + 3 - jump });
    118     return offset + 3;
    119 }
    120 
    121 fn closureInstruction(name: []const u8, ch: *const Obj.Chunk, offset: usize) Error!usize {
    122     var off = offset + 1;
    123     const constant = ch.code.ptr().get(off).?;
    124     const arity = ch.code.ptr().get(off + 1).?;
    125     const count = ch.code.ptr().get(off + 2).?;
    126     off += 3;
    127 
    128     const constval = ch.constants.ptr().get(constant).?;
    129     const chunk = try constval.obj.cast(.Chunk);
    130 
    131     print("{s:<32} {d:4} {d}\n", .{ name, arity, count });
    132     for (0..count) |_| {
    133         const tp = ch.code.ptr().get(off).?;
    134         const idx = ch.code.ptr().get(off + 1).?;
    135         try print_offset(ch, off + 1);
    136         print("{s:<38}|-> {s} {d}\n", .{ "", @tagName(@as(Compiler.Upvalue.Type, @enumFromInt(tp))), idx });
    137         off += 2;
    138     }
    139 
    140     try disassembleChunk(chunk);
    141 
    142     return off + 1;
    143 }