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<u8>,
- _marker: PhantomData<u8>,
+ code: NonNull<OpCode>,
+ _marker: PhantomData<OpCode>,
}
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<u8> {
+ pub fn pop(&mut self) -> Option<OpCode> {
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");
}