commit da3a5e5275ac7f8b7cc108744e0468f16ba4cdc6 Author: William Ball Date: Mon Mar 16 22:20:18 2026 -0400 done with chapter one diff --git a/chunk/chunk.ha b/chunk/chunk.ha new file mode 100644 index 0000000..b831420 --- /dev/null +++ b/chunk/chunk.ha @@ -0,0 +1,79 @@ +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); +}; diff --git a/debug/debug.ha b/debug/debug.ha new file mode 100644 index 0000000..81a787d --- /dev/null +++ b/debug/debug.ha @@ -0,0 +1,57 @@ +use chunk; +use fmt; +use value; + +export fn disassemble_chunk(chunk: *chunk::chunk, name: str) void = { + fmt::printf("== {} ==\n", name)!; + for (let idx = 0z; idx < len(chunk.code)) { + idx = dissassemble_instruction(chunk, idx); + }; +}; + +export fn dissassemble_instruction(chunk: *chunk::chunk, idx: size) size = { + fmt::printf("{:4_0} ", idx)!; + const line = chunk::get_line(chunk, idx); + if (idx > 0 && line == chunk::get_line(chunk, idx - 1)) { + fmt::print(" | ")!; + } else { + fmt::printf("{:4} ", line)!; + }; + let instruction = chunk.code[idx]; + switch (instruction) { + case chunk::opcode::RETURN => + return simple_instruction("RETURN", idx); + case chunk::opcode::CONSTANT => + return constant_instruction("CONSTANT", chunk, idx); + case chunk::opcode::CONSTANT_LONG => + return long_constant_instruction("CONSTANT_LONG", chunk, idx); + case => + fmt::printf("Unknown opcode: {}\n", instruction)!; + return idx + 1; + }; +}; + +fn simple_instruction(name: str, idx: size) size = { + fmt::printf("{}\n", name)!; + return idx + 1; +}; + +fn constant_instruction(name: str, chunk: *chunk::chunk, idx: size) size = { + const constant = chunk.code[idx + 1]; + fmt::printf("{:-16} {:4} '", name, constant)!; + value::print_value(chunk.constants[constant]); + fmt::print("'\n")!; + return idx + 2; +}; + +fn long_constant_instruction(name: str, chunk: *chunk::chunk, idx: size) size = { + const constant1: size = chunk.code[idx + 1]; + const constant2: size = chunk.code[idx + 2]; + const constant3: size = chunk.code[idx + 3]; + const constant = (constant3 << 16) + (constant2 << 8) + constant1; + + fmt::printf("{:-16} {} '", name, constant)!; + value::print_value(chunk.constants[constant]); + fmt::print("'\n")!; + return idx + 4; +}; diff --git a/hlox b/hlox new file mode 100755 index 0000000..202fe6c Binary files /dev/null and b/hlox differ diff --git a/main.ha b/main.ha new file mode 100644 index 0000000..f93203e --- /dev/null +++ b/main.ha @@ -0,0 +1,16 @@ +use chunk; +use debug; +use fmt; +use os; + +export fn main() void = { + let chunk = chunk::new_chunk(); + defer chunk::free_chunk(&chunk); + + chunk::write_constant(&chunk, 1.2, 123); + chunk::write_chunk(&chunk, chunk::opcode::RETURN, 123); + + debug::disassemble_chunk(&chunk, "test chunk"); + + os::exit(0); +}; diff --git a/value/value.ha b/value/value.ha new file mode 100644 index 0000000..1951319 --- /dev/null +++ b/value/value.ha @@ -0,0 +1,7 @@ +use fmt; + +export type value = f64; + +export fn print_value(val: value) void = { + fmt::printf("{}", val)!; +};