14.4
change ttppnowozursnksmulywszkqzpllzwsv
commit 4cedc96da8944635587321b6b03cdcd4492211d4
author Alpha Chen <alpha@kejadlen.dev>
date
parent mtryqztv
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");
 }