diff --git a/rust/src/chunk.rs b/rust/src/chunk.rs index 66ff7f8..d94a15a 100644 --- a/rust/src/chunk.rs +++ b/rust/src/chunk.rs @@ -1,7 +1,9 @@ use std::alloc::{self, Layout}; use std::marker::PhantomData; +use std::ops::Deref; use std::ptr::{self, NonNull}; +#[repr(u8)] pub enum OpCode { Return, } @@ -9,8 +11,8 @@ pub enum OpCode { pub struct Chunk { count: usize, capacity: usize, - code: NonNull, - _marker: PhantomData, + code: NonNull, + _marker: PhantomData, } unsafe impl Send for Chunk {} @@ -27,19 +29,41 @@ impl Chunk { } // https://doc.rust-lang.org/nomicon/vec/vec-push-pop.html - pub fn write(&mut self, byte: u8) { + pub fn write(&mut self, op_code: OpCode) { if self.count == self.capacity { self.grow(); } unsafe { - ptr::write(self.code.as_ptr().add(self.count), byte); + ptr::write(self.code.as_ptr().add(self.count), op_code); } // Can't fail, we'll OOM first. self.count += 1; } + pub fn disassemble(&self, name: &str) { + println!("== {} ==", name); + + let mut offset = 0; + while offset < self.count { + offset = self.disassemble_instruction(offset); + } + } + + fn disassemble_instruction(&self, offset: usize) -> usize { + print!("{:04} ", offset); + + match self[offset] { + OpCode::Return => self.simple_instruction("OP_RETURN", offset), + } + } + + fn simple_instruction(&self, name: &str, offset: usize) -> usize { + println!("{}", name); + offset + 1 + } + // https://doc.rust-lang.org/nomicon/vec/vec-alloc.html fn grow(&mut self) { // Crafting Interpreters: GROW_CAPACITY @@ -74,7 +98,7 @@ impl Chunk { }; // If allocation fails, `new_ptr` will be null, in which case we abort. - self.code = match NonNull::new(new_ptr as *mut u8) { + self.code = match NonNull::new(new_ptr as *mut OpCode) { Some(p) => p, None => alloc::handle_alloc_error(new_layout), }; @@ -82,7 +106,7 @@ impl Chunk { } // https://doc.rust-lang.org/nomicon/vec/vec-push-pop.html - pub fn pop(&mut self) -> Option { + pub fn pop(&mut self) -> Option { if self.count == 0 { None } else { @@ -92,6 +116,12 @@ impl Chunk { } } +impl Default for Chunk { + fn default() -> Self { + Self::new() + } +} + // https://doc.rust-lang.org/nomicon/vec/vec-dealloc.html impl Drop for Chunk { fn drop(&mut self) { @@ -105,8 +135,9 @@ impl Drop for Chunk { } } -impl Default for Chunk { - fn default() -> Self { - Self::new() +impl Deref for Chunk { + type Target = [OpCode]; + fn deref(&self) -> &[OpCode] { + unsafe { std::slice::from_raw_parts(self.code.as_ptr(), self.count) } } } diff --git a/rust/src/main.rs b/rust/src/main.rs index 88c5d67..0e1a343 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,5 +1,10 @@ +use chunk::{Chunk, OpCode}; + pub mod chunk; fn main() { - println!("Hello, world!"); + let mut chunk = Chunk::default(); + chunk.write(OpCode::Return); + + chunk.disassemble("test chunk"); }