-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdebug.cpp
131 lines (124 loc) · 4.88 KB
/
debug.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "debug.hpp"
#include "chunk.hpp"
#include "value.hpp"
#include <iomanip>
#include <iostream>
#include <string_view>
static int constantInstruction(std::string_view name, Chunk *chunk, int offset);
static int jumpInstruction(std::string_view name, int sign, Chunk *chunk,
int offset);
// Disassembles the entire chunk by printing each instruction with its name and
// offset.
void disassembleChunk(Chunk *chunk, std::string_view name) {
std::cout << "== " << name << " ==" << std::endl;
for (std::size_t offset = 0; offset < chunk->code.size();) {
offset = disassembleInstruction(chunk, offset);
}
}
// Handles simple instructions that take no arguments, returning the next
// offset.
int simpleInstruction(std::string_view name, int offset) {
std::cout << name << std::endl;
return offset + 1;
}
// Handles instructions that take a byte argument, such as loading or setting a
// variable.
static int byteInstruction(std::string_view name, Chunk *chunk, int offset) {
uint8_t slot = chunk->code[offset + 1];
std::cout << std::left << std::setw(16) << name << " " << std::setw(4)
<< static_cast<int>(slot) << "\n";
return offset + 2;
}
// Disassembles and prints a single instruction at the given offset in the
// chunk.
int disassembleInstruction(Chunk *chunk, int offset) {
std::cout << std::setfill('0') << std::setw(4) << offset << " ";
if (offset > 0 && chunk->lines[offset] == chunk->lines[offset - 1]) {
std::cout << " | ";
} else {
std::cout << std::setfill(' ') << std::setw(3) << chunk->lines[offset]
<< " ";
}
uint8_t instruction = chunk->code[offset];
switch (static_cast<OpCode>(instruction)) {
case OpCode::OP_RETURN:
return simpleInstruction("OP_RETURN", offset);
case OpCode::OP_CONSTANT:
return constantInstruction("OP_CONSTANT", chunk, offset);
case OpCode::OP_NIL:
return simpleInstruction("OP_NIL", offset);
case OpCode::OP_TRUE:
return simpleInstruction("OP_TRUE", offset);
case OpCode::OP_FALSE:
return simpleInstruction("OP_FALSE", offset);
case OpCode::OP_EQUAL:
return simpleInstruction("OP_EQUAL", offset);
case OpCode::OP_POP:
return simpleInstruction("OP_POP", offset);
case OpCode::OP_GET_LOCAL:
return byteInstruction("OP_GET_LOCAL", chunk, offset);
case OpCode::OP_SET_LOCAL:
return byteInstruction("OP_SET_LOCAL", chunk, offset);
case OpCode::OP_GET_GLOBAL:
return constantInstruction("OP_GET_GLOBAL", chunk, offset);
case OpCode::OP_DEFINE_GLOBAL:
return constantInstruction("OP_DEFINE_GLOBAL", chunk, offset);
case OpCode::OP_SET_GLOBAL:
return constantInstruction("OP_SET_GLOBAL", chunk, offset);
case OpCode::OP_GREATER:
return simpleInstruction("OP_GREATER", offset);
case OpCode::OP_LESS:
return simpleInstruction("OP_LESS", offset);
case OpCode::OP_ADD:
return simpleInstruction("OP_ADD", offset);
case OpCode::OP_SUBTRACT:
return simpleInstruction("OP_SUBTRACT", offset);
case OpCode::OP_MULTIPLY:
return simpleInstruction("OP_MULTIPLY", offset);
case OpCode::OP_DIVIDE:
return simpleInstruction("OP_DIVIDE", offset);
case OpCode::OP_NOT:
return simpleInstruction("OP_NOT", offset);
case OpCode::OP_NEGATE:
return simpleInstruction("OP_NEGATE", offset);
case OpCode::OP_PRINT:
return simpleInstruction("OP_PRINT", offset);
case OpCode::OP_DUP:
return simpleInstruction("OP_DUP", offset);
case OpCode::OP_JUMP:
return jumpInstruction("OP_JUMP", 1, chunk, offset);
case OpCode::OP_JUMP_IF_FALSE:
return jumpInstruction("OP_JUMP_IF_FALSE", 1, chunk, offset);
case OpCode::OP_LOOP:
return jumpInstruction("OP_LOOP", -1, chunk, offset);
case OpCode::OP_BUILD_LIST:
return byteInstruction("OP_BUILD_LIST", chunk, offset);
case OpCode::OP_INDEX_SUBSCR:
return simpleInstruction("OP_INDEX_SUBSCR", offset);
default:
std::cout << "Unknown opcode " << static_cast<int>(instruction)
<< std::endl;
return offset + 1;
}
}
// Handles jump instructions by reading the jump offset and printing the jump
// target.
static int jumpInstruction(std::string_view name, int sign, Chunk *chunk,
int offset) {
uint16_t jump = static_cast<uint16_t>(chunk->code[offset + 1] << 8);
jump |= chunk->code[offset + 2];
std::cout << std::left << std::setw(16) << name << " " << std::setw(4)
<< offset << " -> " << (offset + 3 + sign * jump) << std::endl;
return offset + 3;
}
// Handles constant-related instructions, printing the constant index and its
// value.
static int constantInstruction(std::string_view name, Chunk *chunk,
int offset) {
uint8_t constant = chunk->code[offset + 1];
std::cout << std::left << std::setw(16) << name << std::right << std::setw(4)
<< static_cast<int>(constant) << " '";
printValue(chunk->constants[constant]);
std::cout << "'\n";
return offset + 2;
}