commit 5cee345e8bb31524e2ff96e5c442026849ef511f Author: publicmatt Date: Thu May 2 11:30:50 2024 -0700 add return and const instructions. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..9862c74 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "mox" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..cbf984b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "mox" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/debug.rs b/src/debug.rs new file mode 100644 index 0000000..6fa2ff5 --- /dev/null +++ b/src/debug.rs @@ -0,0 +1,44 @@ +use mox::value::Value; +use mox::{Chunk, ConversionError, OptCode}; + +pub fn disassemble_chunk(chunk: &Chunk, name: &str) { + // println!("{:?}", chunk); + println!("== {} ==", name); + let mut offset = 0; + while offset < chunk.code.len() { + offset = disassemble_instruction(&chunk, offset); + } +} +fn disassemble_instruction(chunk: &Chunk, offset: usize) -> usize { + print!("{:04} ", offset); + let instruction: Result = chunk.code[offset].try_into(); + match instruction { + Ok(code) => match code { + OptCode::OpConstant => { + return constant_instruction("OpConstant", chunk, offset); + } + OptCode::OpReturn => { + return simple_instruction("OpReturn", offset); + } + }, + Err(e) => { + println!("Unknown optcode {:?}", e); + return offset + 1; + } + } +} + +fn simple_instruction(name: &str, offset: usize) -> usize { + println!("{}", name); + return offset + 1; +} +fn constant_instruction(name: &str, chunk: &Chunk, offset: usize) -> usize { + let constant: u8 = chunk.code[offset + 1]; + print!("{:<16} {:>4} ", name, constant); + print_value(chunk.constants[constant as usize]); + println!(); + return offset + 2; +} +fn print_value(value: Value) { + print!("{:}", value); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..d02ac1c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,82 @@ +pub mod value; + +use value::Value; + +#[derive(Debug, PartialEq, Eq)] +pub enum OptCode { + OpReturn, + OpConstant, +} +#[derive(Debug)] +pub struct Chunk { + pub code: Vec, + pub constants: Vec, +} + +impl From for u8 { + fn from(code: OptCode) -> Self { + match code { + OptCode::OpReturn => 0, + OptCode::OpConstant => 1, + } + } +} +#[derive(Debug)] +pub struct ConversionError; + +impl TryFrom for OptCode { + type Error = ConversionError; + fn try_from(code: u8) -> Result { + match code { + 0 => Ok(OptCode::OpReturn), + 1 => Ok(OptCode::OpConstant), + _ => Err(ConversionError), + } + } +} + +impl Chunk { + pub fn new() -> Self { + Self { + code: vec![], + constants: vec![], + } + } + pub fn write(&mut self, byte: u8) { + self.code.push(byte); + } + pub fn write_value(&mut self, add: Value) -> u8 { + self.constants.push(add); + return (self.constants.len() - 1).try_into().unwrap(); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn u8_to_optcode() { + let pred: OptCode = 0.try_into().unwrap(); + assert_eq!(pred, OptCode::OpReturn); + let pred: OptCode = 1.try_into().unwrap(); + assert_eq!(pred, OptCode::OpConstant); + } + #[test] + fn basic_write() { + let mut chunk = Chunk::new(); + let constant_idx: u8 = chunk.write_value(1.2); + assert_eq!(constant_idx, 0); + chunk.write(OptCode::OpConstant.into()); + chunk.write(constant_idx); + let pred: OptCode = chunk.code[0].try_into().unwrap(); + assert_eq!(pred, OptCode::OpConstant); + } + #[test] + fn try_into_constant() { + let mut chunk = Chunk::new(); + let constant_idx: u8 = chunk.write_value(1.2); + chunk.write(OptCode::OpConstant.into()); + chunk.write(constant_idx); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..fee608d --- /dev/null +++ b/src/main.rs @@ -0,0 +1,15 @@ +use mox::Chunk; +use mox::OptCode; +mod debug; + +use debug::disassemble_chunk; + +fn main() { + let mut chunk = Chunk::new(); + let constant_idx: u8 = chunk.write_value(1.2); + chunk.write(OptCode::OpConstant.into()); + chunk.write(constant_idx); + chunk.write(OptCode::OpReturn.into()); + + disassemble_chunk(&chunk, "test chunk"); +} diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 0000000..343d142 --- /dev/null +++ b/src/value.rs @@ -0,0 +1 @@ +pub type Value = f64;