done with chapter one
This commit is contained in:
commit
da3a5e5275
5 changed files with 159 additions and 0 deletions
79
chunk/chunk.ha
Normal file
79
chunk/chunk.ha
Normal file
|
|
@ -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);
|
||||
};
|
||||
57
debug/debug.ha
Normal file
57
debug/debug.ha
Normal file
|
|
@ -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;
|
||||
};
|
||||
BIN
hlox
Executable file
BIN
hlox
Executable file
Binary file not shown.
16
main.ha
Normal file
16
main.ha
Normal file
|
|
@ -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);
|
||||
};
|
||||
7
value/value.ha
Normal file
7
value/value.ha
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
use fmt;
|
||||
|
||||
export type value = f64;
|
||||
|
||||
export fn print_value(val: value) void = {
|
||||
fmt::printf("{}", val)!;
|
||||
};
|
||||
Loading…
Reference in a new issue