Alpha Chen 2 years ago
parent 56c2885565
commit f8b030152e

@ -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) }
}
}

@ -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");
}

Loading…
Cancel
Save