Alpha Chen 2 years ago
parent 56c2885565
commit f8b030152e

@ -1,7 +1,9 @@
use std::alloc::{self, Layout}; use std::alloc::{self, Layout};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::Deref;
use std::ptr::{self, NonNull}; use std::ptr::{self, NonNull};
#[repr(u8)]
pub enum OpCode { pub enum OpCode {
Return, Return,
} }
@ -9,8 +11,8 @@ pub enum OpCode {
pub struct Chunk { pub struct Chunk {
count: usize, count: usize,
capacity: usize, capacity: usize,
code: NonNull<u8>, code: NonNull<OpCode>,
_marker: PhantomData<u8>, _marker: PhantomData<OpCode>,
} }
unsafe impl Send for Chunk {} unsafe impl Send for Chunk {}
@ -27,19 +29,41 @@ impl Chunk {
} }
// https://doc.rust-lang.org/nomicon/vec/vec-push-pop.html // 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 { if self.count == self.capacity {
self.grow(); self.grow();
} }
unsafe { 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. // Can't fail, we'll OOM first.
self.count += 1; 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 // https://doc.rust-lang.org/nomicon/vec/vec-alloc.html
fn grow(&mut self) { fn grow(&mut self) {
// Crafting Interpreters: GROW_CAPACITY // Crafting Interpreters: GROW_CAPACITY
@ -74,7 +98,7 @@ impl Chunk {
}; };
// If allocation fails, `new_ptr` will be null, in which case we abort. // 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, Some(p) => p,
None => alloc::handle_alloc_error(new_layout), None => alloc::handle_alloc_error(new_layout),
}; };
@ -82,7 +106,7 @@ impl Chunk {
} }
// https://doc.rust-lang.org/nomicon/vec/vec-push-pop.html // 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 { if self.count == 0 {
None None
} else { } 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 // https://doc.rust-lang.org/nomicon/vec/vec-dealloc.html
impl Drop for Chunk { impl Drop for Chunk {
fn drop(&mut self) { fn drop(&mut self) {
@ -105,8 +135,9 @@ impl Drop for Chunk {
} }
} }
impl Default for Chunk { impl Deref for Chunk {
fn default() -> Self { type Target = [OpCode];
Self::new() fn deref(&self) -> &[OpCode] {
unsafe { std::slice::from_raw_parts(self.code.as_ptr(), self.count) }
} }
} }

@ -1,5 +1,10 @@
use chunk::{Chunk, OpCode};
pub mod chunk; pub mod chunk;
fn main() { fn main() {
println!("Hello, world!"); let mut chunk = Chunk::default();
chunk.write(OpCode::Return);
chunk.disassemble("test chunk");
} }

Loading…
Cancel
Save