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); };