-
Notifications
You must be signed in to change notification settings - Fork 0
/
debug.c
140 lines (126 loc) · 5.02 KB
/
debug.c
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
132
133
134
135
136
137
138
139
140
#include <stdio.h>
#include "debug.h"
#include "chunk.h"
#include "object.h"
void disassembleChunk(Chunk* chunk, const char *name) {
printf("== %s ==\n", name);
for (int offset = 0; offset < chunk->count;)
offset = disassembleInstruction(chunk, offset);
}
static int simpleInstruction(const char* name, int offset) {
printf("%s\n", name);
return offset + 1;
}
static int byteInstruction(const char* name, Chunk* chunk, int offset) {
uint8_t slot = chunk->code[offset + 1];
printf("%-16s %4d\n", name, slot);
return offset + 2;
}
static int jumpInstruction(const char* name, int sign, Chunk* chunk, int offset) {
uint16_t jump = (uint16_t)(chunk->code[offset + 1] << 8);
jump |= chunk->code[offset + 2];
printf("%-16s %4d -> %d\n", name, offset, offset + 3 + sign * jump);
return offset + 3;
}
static int constantInstruction(const char* name, Chunk* chunk, int offset) {
uint8_t constant = chunk->code[offset + 1]; // accessing index of the constant
printf("%-16s %d '", name, constant);
printValue(chunk->constants.values[constant]);
printf("'\n");
return offset + 2;
}
/*
disassembleInstruction returns a number to tell the caller the
offset of the beginning of the next instruction
*/
int disassembleInstruction(Chunk* chunk, int offset) {
printf("%04d ", offset); // prints the byte offset of each instruction
if (offset > 0 && chunk->lines[offset] == chunk->lines[offset - 1])
printf(" | "); // we show a '|' for any instruction that comes from the same source line as the preceding one
else printf("%4d ", chunk->lines[offset]);
uint8_t instruction = chunk->code[offset]; // reads single byte from bytecode
switch (instruction) {
case OP_CONSTANT:
return constantInstruction("OP_CONSTANT", chunk, offset);
case OP_NIL:
return simpleInstruction("OP_NIL", offset);
case OP_TRUE:
return simpleInstruction("OP_TRUE", offset);
case OP_FALSE:
return simpleInstruction("OP_FALSE", offset);
case OP_POP:
return simpleInstruction("OP_POP", offset);
case OP_GET_LOCAL:
return byteInstruction("OP_GET_LOCAL", chunk, offset);
case OP_SET_LOCAL:
return byteInstruction("OP_SET_LOCAL", chunk, offset);
case OP_GET_GLOBAL:
return constantInstruction("OP_GET_GLOBAL", chunk, offset);
case OP_DEFINE_GLOBAL:
return constantInstruction("OP_DEFINE_GLOBAL", chunk, offset);
case OP_SET_GLOBAL:
return constantInstruction("OP_SET_GLOBAL", chunk, offset);
case OP_GET_UPVALUE:
return byteInstruction("OP_GET_UPVALUE", chunk, offset);
case OP_SET_UPVALUE:
return byteInstruction("OP_SET_UPVALUE", chunk, offset);
case OP_EQUAL:
return simpleInstruction("OP_EQUAL", offset);
case OP_GREATER:
return simpleInstruction("OP_GREATER", offset);
case OP_LESS:
return simpleInstruction("OP_LESS", offset);
case OP_ADD:
return simpleInstruction("OP_ADD", offset);
case OP_SUBTRACT:
return simpleInstruction("OP_SUBTRACT", offset);
case OP_MULTIPLY:
return simpleInstruction("OP_MULTIPLY", offset);
case OP_DIVIDE:
return simpleInstruction("OP_DIVIDE", offset);
case OP_NOT:
return simpleInstruction("OP_NOT", offset);
case OP_NEGATE:
return simpleInstruction("OP_NEGATE", offset);
case OP_PRINT:
return simpleInstruction("OP_PRINT", offset);
case OP_JUMP:
return jumpInstruction("OP_JUMP", 1, chunk, offset);
case OP_JUMP_IF_FALSE:
return jumpInstruction("OP_JUMP_IF_FALSE", 1, chunk, offset);
case OP_LOOP:
return jumpInstruction("OP_LOOP", -1, chunk, offset);
case OP_CALL:
return byteInstruction("OP_CALL", chunk, offset);
case OP_CLOSURE: {
offset++;
uint8_t constant = chunk->code[offset++];
printf("%-16s %4d ", "OP_CLOSURE", constant);
printValue(chunk->constants.values[constant]);
printf("\n");
ObjFunction* function = AS_FUNCTION(
chunk->constants.values[constant]
);
for (int j = 0; j < function->upvalueCount; ++j) {
int isLocal = chunk->code[offset++];
int index = chunk->code[offset++];
printf("%04d | %s %d\n",
offset - 2, isLocal ? "local" : "upvalue",
index);
}
return offset;
}
case OP_CLOSE_UPVALUE:
return simpleInstruction("OP_CLOSE_UPVALUE", offset);
case OP_RETURN:
return simpleInstruction("OP_RETURN", offset);
default:
printf("Unknown opcode %d\n", instruction);
return offset + 1;
}
}
/*
Example:
== test chunk ==
0000 OP_RETURN
*/