diff --git a/src/chunk.rs b/src/chunk.rs index f7f87e3..d88d7fa 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -1,6 +1,6 @@ use tracing::debug; use crate::value::Value; -use crate::{ +use crate::vm::{ OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_FALSE, OP_MULTIPLY, OP_NEGATE, OP_RETURN, OP_SUBTRACT, OP_TRUE, OP_NOT, OP_SHL, OP_SHR }; diff --git a/src/compiler.rs b/src/compiler.rs index 42a82f4..45e430b 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -2,7 +2,7 @@ use crate::chunk::Chunk; use crate::scanner::scan; use crate::tokens::{Token, TokenType}; use crate::value::Value; -use crate::{OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_FALSE, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_RETURN, OP_SHR, OP_SHL, OP_SUBTRACT, OP_TRUE}; +use crate::vm::{OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_FALSE, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_RETURN, OP_SHR, OP_SHL, OP_SUBTRACT, OP_TRUE}; use anyhow::anyhow; use std::collections::HashMap; use std::sync::LazyLock; diff --git a/src/lib.rs b/src/lib.rs index 4a16f82..c14de4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,137 +10,4 @@ pub mod opcode; pub mod scanner; mod tokens; mod value; - -pub fn interpret(chunk: Chunk) -> Result { - let mut vm = Vm { - chunk, - ip: 0, - stack: vec![], - }; - vm.run() -} - -pub struct Vm { - chunk: Chunk, - ip: usize, - stack: Vec, -} - -impl Vm { - fn run(&mut self) -> Result { - loop { - debug!("["); - for value in self.stack.iter() { - debug!("{:?} ", value); - } - debug!("]"); - let opcode = self.chunk.code[self.ip]; - self.ip += 1; - match opcode { - OP_CONSTANT => { - let value = &self.chunk.constants[self.chunk.code[self.ip] as usize]; - self.ip += 1; - self.push(value.clone()); - } - OP_FALSE => self.push(Value::Bool(false)), - OP_TRUE => self.push(Value::Bool(true)), - OP_ADD => binary_op(self, |a, b| a + b), - OP_SUBTRACT => binary_op(self, |a, b| a - b), - OP_MULTIPLY => binary_op(self, |a, b| a * b), - OP_DIVIDE => binary_op(self, |a, b| a / b), - OP_AND => binary_op(self, |a, b| { - if let (Value::Bool(a), Value::Bool(b)) = (a, b) { - Ok(Value::Bool(*a && *b)) - } else { - Err(anyhow!("Cannot and")) - } - }), - OP_OR => binary_op(self, |a, b| { - if let (Value::Bool(a), Value::Bool(b)) = (a, b) { - Ok(Value::Bool(*a || *b)) - } else { - Err(anyhow!("Cannot compare")) - } - }), - OP_NOT => unary_op(self, |a| !a), - OP_BITAND => binary_op(self, |a, b| a & b), - OP_BITOR => binary_op(self, |a, b| a | b), - OP_BITXOR => binary_op(self, |a, b| a ^ b), - OP_NEGATE => unary_op(self, |a| -a), - OP_RETURN => { - // println!("{:?}", self.pop()); - return Result::Ok(self.pop()); - } - OP_SHL => binary_op(self, |a, b| a << b), - OP_SHR => binary_op(self, |a, b| a >> b), - _ => {} - } - } - } - - fn reset_stack(&mut self) { - self.stack.clear(); - } - - fn push(&mut self, value: Value) { - self.stack.push(value); - } - - fn pop(&mut self) -> Value { - self.stack - .pop() - .unwrap_or_else(|| Value::Error("Error occurred".to_string())) - } -} - -fn binary_op(vm: &mut Vm, op: impl Fn(&Value, &Value) -> anyhow::Result + Copy) { - let a = vm.pop(); - let b = vm.pop(); - - let result = op(&a, &b); - match result { - Ok(result) => vm.push(result), - Err(e) => println!("Error: {} {:?} and {:?}", e.to_string(), a, b), - } -} - -fn unary_op(stack: &mut Vm, op: impl Fn(&Value) -> anyhow::Result + Copy) { - let a = stack.pop(); - let result = op(&a); - match result { - Ok(result) => stack.push(result), - Err(e) => panic!("Error: {:?} {:?}", e, a), - } -} - -#[derive(Debug)] -pub enum Result { - Ok(Value), - CompileError, - Error, -} - -pub const OP_CONSTANT: u16 = 1; -pub const OP_ADD: u16 = 2; -pub const OP_SUBTRACT: u16 = 3; -pub const OP_MULTIPLY: u16 = 4; -pub const OP_DIVIDE: u16 = 5; -pub const OP_NEGATE: u16 = 6; -pub const OP_PRINT: u16 = 7; -pub const OP_RETURN: u16 = 8; -pub const OP_TRUE: u16 = 9; -pub const OP_FALSE: u16 = 10; -pub const OP_AND: u16 = 11; -pub const OP_OR: u16 = 12; -pub const OP_NOT: u16 = 13; -pub const OP_EQUAL: u16 = 14; -pub const OP_GREATER: u16 = 15; -pub const OP_LESS: u16 = 16; -pub const OP_NOT_EQUAL: u16 = 17; -pub const OP_GREATER_EQUAL: u16 = 18; -pub const OP_LESS_EQUAL: u16 = 19; -pub const OP_BITAND: u16 = 20; -pub const OP_BITOR: u16 = 21; -pub const OP_BITXOR: u16 = 22; -pub const OP_SHR: u16 = 23; -pub const OP_SHL: u16 = 24; +pub mod vm; diff --git a/src/main.rs b/src/main.rs index fc512e9..55b879a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,11 @@ -// use crudlang::chunk::Chunk; -use crudlang::compiler::compile; -use crudlang::interpret; -// use crudlang::scanner::scan; fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); - // let mut chunk = Chunk::new("main"); - // let constant = chunk.add_constant(1.2); - // chunk.add(crudlang::opcode::OP_CONSTANT, 123); - // chunk.add(constant as u16, 123); - // chunk.add(crudlang::opcode::OP_NEGATE, 123); - // - // let constant = chunk.add_constant(3.4); - // chunk.add(crudlang::opcode::OP_CONSTANT, 123); - // chunk.add(constant as u16, 123); - // chunk.add(crudlang::opcode::OP_ADD, 123); - // - // chunk.add(crudlang::opcode::OP_RETURN, 123); - let chunk = compile("3<<2")?; + + let chunk = crudlang::compiler::compile("3<<2")?; chunk.disassemble(); - let result = interpret(chunk); + let result = crudlang::vm::interpret(chunk); println!("{:?}", result); Ok(()) } diff --git a/src/vm.rs b/src/vm.rs new file mode 100644 index 0000000..354dd13 --- /dev/null +++ b/src/vm.rs @@ -0,0 +1,138 @@ +use anyhow::anyhow; +use tracing::debug; +use crate::chunk::Chunk; +use crate::value::Value; + +pub fn interpret(chunk: Chunk) -> Result { + let mut vm = Vm { + chunk, + ip: 0, + stack: vec![], + }; + vm.run() +} + +pub struct Vm { + chunk: Chunk, + ip: usize, + stack: Vec, +} + +impl Vm { + fn run(&mut self) -> Result { + loop { + debug!("["); + for value in self.stack.iter() { + debug!("{:?} ", value); + } + debug!("]"); + let opcode = self.chunk.code[self.ip]; + self.ip += 1; + match opcode { + OP_CONSTANT => { + let value = &self.chunk.constants[self.chunk.code[self.ip] as usize]; + self.ip += 1; + self.push(value.clone()); + } + OP_FALSE => self.push(Value::Bool(false)), + OP_TRUE => self.push(Value::Bool(true)), + OP_ADD => binary_op(self, |a, b| a + b), + OP_SUBTRACT => binary_op(self, |a, b| a - b), + OP_MULTIPLY => binary_op(self, |a, b| a * b), + OP_DIVIDE => binary_op(self, |a, b| a / b), + OP_AND => binary_op(self, |a, b| { + if let (Value::Bool(a), Value::Bool(b)) = (a, b) { + Ok(Value::Bool(*a && *b)) + } else { + Err(anyhow!("Cannot and")) + } + }), + OP_OR => binary_op(self, |a, b| { + if let (Value::Bool(a), Value::Bool(b)) = (a, b) { + Ok(Value::Bool(*a || *b)) + } else { + Err(anyhow!("Cannot compare")) + } + }), + OP_NOT => unary_op(self, |a| !a), + OP_BITAND => binary_op(self, |a, b| a & b), + OP_BITOR => binary_op(self, |a, b| a | b), + OP_BITXOR => binary_op(self, |a, b| a ^ b), + OP_NEGATE => unary_op(self, |a| -a), + OP_RETURN => { + // println!("{:?}", self.pop()); + return Result::Ok(self.pop()); + } + OP_SHL => binary_op(self, |a, b| a << b), + OP_SHR => binary_op(self, |a, b| a >> b), + _ => {} + } + } + } + + fn reset_stack(&mut self) { + self.stack.clear(); + } + + fn push(&mut self, value: Value) { + self.stack.push(value); + } + + fn pop(&mut self) -> Value { + self.stack + .pop() + .unwrap_or_else(|| Value::Error("Error occurred".to_string())) + } +} + +fn binary_op(vm: &mut Vm, op: impl Fn(&Value, &Value) -> anyhow::Result + Copy) { + let a = vm.pop(); + let b = vm.pop(); + + let result = op(&a, &b); + match result { + Ok(result) => vm.push(result), + Err(e) => println!("Error: {} {:?} and {:?}", e.to_string(), a, b), + } +} + +fn unary_op(stack: &mut Vm, op: impl Fn(&Value) -> anyhow::Result + Copy) { + let a = stack.pop(); + let result = op(&a); + match result { + Ok(result) => stack.push(result), + Err(e) => panic!("Error: {:?} {:?}", e, a), + } +} + +#[derive(Debug)] +pub enum Result { + Ok(Value), + CompileError, + Error, +} + +pub const OP_CONSTANT: u16 = 1; +pub const OP_ADD: u16 = 2; +pub const OP_SUBTRACT: u16 = 3; +pub const OP_MULTIPLY: u16 = 4; +pub const OP_DIVIDE: u16 = 5; +pub const OP_NEGATE: u16 = 6; +pub const OP_PRINT: u16 = 7; +pub const OP_RETURN: u16 = 8; +pub const OP_TRUE: u16 = 9; +pub const OP_FALSE: u16 = 10; +pub const OP_AND: u16 = 11; +pub const OP_OR: u16 = 12; +pub const OP_NOT: u16 = 13; +pub const OP_EQUAL: u16 = 14; +pub const OP_GREATER: u16 = 15; +pub const OP_LESS: u16 = 16; +pub const OP_NOT_EQUAL: u16 = 17; +pub const OP_GREATER_EQUAL: u16 = 18; +pub const OP_LESS_EQUAL: u16 = 19; +pub const OP_BITAND: u16 = 20; +pub const OP_BITOR: u16 = 21; +pub const OP_BITXOR: u16 = 22; +pub const OP_SHR: u16 = 23; +pub const OP_SHL: u16 = 24;