-
Notifications
You must be signed in to change notification settings - Fork 0
/
chunk.c
92 lines (71 loc) · 2.3 KB
/
chunk.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
#include "chunk.h"
#include "memory.h"
#include "value.h"
void Chunk_init(Chunk* chunk) {
chunk->code = NULL;
chunk->count = 0;
chunk->capacity = 0;
chunk->line_capacity = 0;
chunk->line_count = 0;
chunk->lines = NULL;
ValueArray_init(&chunk->constants);
}
void Chunk_write(Chunk* chunk, uint8_t byte, size_t line) {
if (chunk->capacity < chunk->count + 1) {
size_t old_capacity = chunk->capacity;
chunk->capacity = GROW_CAPACITY(old_capacity);
chunk->code = GROW_ARRAY(uint8_t, chunk->code, old_capacity, chunk->capacity);
}
chunk->code[chunk->count] = byte;
chunk->count++;
if (chunk->line_count > 0 &&
chunk->lines[chunk->line_count - 1].line == line) {
return;
}
if (chunk->line_capacity < chunk->line_count + 1) {
size_t old_capacity = chunk->line_capacity;
chunk->line_capacity = GROW_CAPACITY(old_capacity);
chunk->lines = GROW_ARRAY(LineStart, chunk->lines, old_capacity, chunk->line_capacity);
}
LineStart * line_start = &chunk->lines[chunk->line_count++];
line_start->offset = chunk->count - 1;
line_start->line = line;
}
size_t Chunk_add_constant(Chunk* chunk, Value value) {
ValueArray_write(&chunk->constants, value);
return chunk->constants.count - 1;
}
void Chunk_write_constant(Chunk *chunk, Value value, size_t line) {
size_t addr = Chunk_add_constant(chunk, value);
if (addr <= 0xff) {
Chunk_write(chunk, OP_LOAD_CONST, line);
Chunk_write(chunk, addr, line);
return;
}
Chunk_write(chunk, OP_LOAD_CONST_LONG, line);
Chunk_write(chunk, (addr >> 0) & 0xff, line);
Chunk_write(chunk, (addr >> 8) & 0xff, line);
Chunk_write(chunk, (addr >> 16) & 0xff, line);
}
size_t Chunk_get_line(Chunk* chunk, size_t instruction) {
size_t start = 0;
size_t end = chunk->line_count - 1;
for (;;) {
size_t mid = ((end - start) / 2) + start;
LineStart* line = &chunk->lines[mid];
if (instruction < line->offset) {
end = mid - 1;
} else if (mid == chunk->line_count - 1 ||
instruction < chunk->lines[mid + 1].offset) {
return line->line;
} else {
start = mid + 1;
}
}
}
void Chunk_free(Chunk* chunk) {
FREE_ARRAY(uint8_t, chunk->code, chunk->capacity);
FREE_ARRAY(LineStart, chunk->lines, chunk->line_capacity);
ValueArray_free(&chunk->constants);
Chunk_init(chunk);
}