hlox/chunk/chunk.ha

79 lines
1.8 KiB
Hare

use value;
use log;
export type opcode = enum u8 {
RETURN,
CONSTANT,
CONSTANT_LONG,
};
export type line_code = struct {
line: size,
num: size,
};
export type chunk = struct {
code: []u8,
constants: []value::value,
lines: []line_code,
};
export fn new_chunk() chunk = {
return chunk {
code = [],
constants = [],
lines = [],
};
};
export fn get_line(this_chunk: *chunk, idx: size) size = {
let total = 0z;
for (let line .. this_chunk.lines) {
total += line.num;
if (total >= idx) {
return line.line;
};
};
log::fatalf("{} out of bounds", idx);
};
export fn write_chunk(this_chunk: *chunk, byte: u8, line: size) void = {
append(this_chunk.code, byte)!;
const num_lines = len(this_chunk.lines);
if (num_lines == 0 ||
line != this_chunk.lines[num_lines - 1].line)
{
append(this_chunk.lines, line_code {
line = line,
num = 1,
})!;
} else {
this_chunk.lines[num_lines - 1].num += 1;
};
};
export fn add_constant(this_chunk: *chunk, value: value::value) size = {
append(this_chunk.constants, value)!;
return len(this_chunk.constants) - 1;
};
export fn write_constant(this_chunk: *chunk, value: value::value, line: size) void = {
const constant = add_constant(this_chunk, value);
if (constant <= 1 << 8) {
write_chunk(this_chunk, opcode::CONSTANT, line);
write_chunk(this_chunk, constant : u8, line);
} else if (constant <= 1 << 24) {
write_chunk(this_chunk, opcode::CONSTANT_LONG, line);
write_chunk(this_chunk, (constant & 0xFF) : u8, line);
write_chunk(this_chunk, ((constant >> 8) & 0xFF) : u8, line);
write_chunk(this_chunk, ((constant >> 16) & 0xFF) : u8, line);
} else {
log::fatalf("Maximum of {} constants surpassed!", 1 << 24);
};
};
export fn free_chunk(this_chunk: *chunk) void = {
free(this_chunk.code);
free(this_chunk.constants);
free(this_chunk.lines);
};