diff --git a/src/main.rs b/src/main.rs index e52b828..d2fe5a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ use crate::{ TokenStream, lexer::{Token, tokenize}, }, - vm::{RustFunction, VirtualMachine}, + vm::{RuntimeError, RustFunction, VirtualMachine}, }; mod ast; @@ -19,24 +19,24 @@ static TEST: &str = include_str!("../examples/test.lua"); #[derive(Debug)] pub struct Max; impl RustFunction for Max { - fn execute(&self, parameters: Vec) -> Vec { + fn execute(&self, parameters: Vec) -> Result, RuntimeError> { let lhs = parameters.get(0).cloned().unwrap_or(vm::Value::Nil); let rhs = parameters.get(1).cloned().unwrap_or(vm::Value::Nil); - match lhs.lt(&rhs) { + match lhs.lt(&rhs)? { vm::Value::Number(value) => { let res = LuaNumber::from_bits(value); - vec![if res > 0. { rhs } else { lhs }] + Ok(vec![if res > 0. { rhs } else { lhs }]) } - _ => vec![vm::Value::Nil], + _ => Ok(vec![vm::Value::Nil]), } } } #[derive(Debug)] pub struct Print; impl RustFunction for Print { - fn execute(&self, parameters: Vec) -> Vec { + fn execute(&self, parameters: Vec) -> Result, RuntimeError> { println!("{:?}", parameters); - Vec::new() + Ok(Vec::new()) } } @@ -89,7 +89,7 @@ fn main() { let mut run = closure.run(Vec::new()); - while run.next().is_none() {} + while run.next().unwrap().is_none() {} dbg!(&vm.environment.borrow().globals); } diff --git a/src/vm.rs b/src/vm.rs index 4089b7e..a837b3e 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,6 +1,8 @@ +use thiserror::Error; + use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc}; -use crate::ast::LuaNumber; +use crate::ast::{BinaryOperator, LuaNumber, UnaryOperator}; pub type VMNumber = u64; @@ -96,6 +98,16 @@ impl Debug for Instruction { } } +#[derive(Error, Debug)] +pub enum RuntimeError { + #[error("Unable to perform {0:?} operator between {1:?} and {2:?}")] + InvalidOperands(BinaryOperator, Value, Value), + #[error("Unable to perform {0:?} operator to {1:?}")] + InvalidOperand(UnaryOperator, Value), + #[error("{0}")] + Custom(String), +} + #[derive(Debug, Clone, Default)] pub struct Environment { pub globals: HashMap, @@ -110,87 +122,106 @@ pub enum Value { } impl Value { - pub fn add(&self, other: &Value) -> Value { + pub fn add(&self, other: &Value) -> Result { match (self, other) { (Value::Number(lhs), Value::Number(rhs)) => { let res = LuaNumber::from_bits(*lhs) + LuaNumber::from_bits(*rhs); - Value::Number(res.to_bits()) + Ok(Value::Number(res.to_bits())) } - _ => Value::Nil, + _ => Err(RuntimeError::InvalidOperands( + BinaryOperator::Add, + self.clone(), + other.clone(), + )), } } - pub fn eq(&self, other: &Value) -> Value { + pub fn eq(&self, other: &Value) -> Result { match (self, other) { (Value::Number(lhs), Value::Number(rhs)) => { let res = lhs == rhs; - Value::Number((res as u64 as f64).to_bits()) + Ok(Value::Number((res as u64 as f64).to_bits())) } - _ => Value::Nil, + _ => Err(RuntimeError::InvalidOperands( + BinaryOperator::Equal, + self.clone(), + other.clone(), + )), } } - pub fn lt(&self, other: &Value) -> Value { + pub fn lt(&self, other: &Value) -> Result { match (self, other) { (Value::Number(lhs), Value::Number(rhs)) => { let res = LuaNumber::from_bits(*lhs) < LuaNumber::from_bits(*rhs); - Value::Number((res as u64 as f64).to_bits()) + Ok(Value::Number((res as u64 as f64).to_bits())) } - _ => Value::Nil, + _ => Err(RuntimeError::InvalidOperands( + BinaryOperator::LessThan, + self.clone(), + other.clone(), + )), } } - pub fn lte(&self, other: &Value) -> Value { + pub fn lte(&self, other: &Value) -> Result { match (self, other) { (Value::Number(lhs), Value::Number(rhs)) => { let res = LuaNumber::from_bits(*lhs) <= LuaNumber::from_bits(*rhs); - Value::Number((res as u64 as f64).to_bits()) + Ok(Value::Number((res as u64 as f64).to_bits())) } - _ => Value::Nil, + _ => Err(RuntimeError::InvalidOperands( + BinaryOperator::LessThanOrEqual, + self.clone(), + other.clone(), + )), } } - pub fn unm(&self) -> Value { + pub fn unm(&self) -> Result { match self { Value::Number(lhs) => { let res = -LuaNumber::from_bits(*lhs); - Value::Number(res.to_bits()) + Ok(Value::Number(res.to_bits())) } - _ => Value::Nil, + _ => Err(RuntimeError::InvalidOperand( + UnaryOperator::Negation, + self.clone(), + )), } } - pub fn and(&self, other: &Value) -> Value { + pub fn and(&self, other: &Value) -> Result { match (self, other) { - (Value::Nil, _) | (_, Value::Nil) => Value::Nil, + (Value::Nil, _) | (_, Value::Nil) => Ok(Value::Nil), (Value::Number(lhs), Value::Number(rhs)) => { let res = LuaNumber::from_bits(*lhs) > 0. && LuaNumber::from_bits(*rhs) > 0.; - Value::Number((res as u64 as f64).to_bits()) + Ok(Value::Number((res as u64 as f64).to_bits())) } (Value::Number(value), _) | (_, Value::Number(value)) => { let res = LuaNumber::from_bits(*value) > 0.; - Value::Number((res as u64 as f64).to_bits()) + Ok(Value::Number((res as u64 as f64).to_bits())) } - _ => Value::Nil, + _ => Ok(Value::Nil), } } - pub fn or(&self, other: &Value) -> Value { + pub fn or(&self, other: &Value) -> Result { match (self, other) { - (Value::Nil, value) | (value, Value::Nil) => value.clone(), + (Value::Nil, value) | (value, Value::Nil) => Ok(value.clone()), (Value::Number(lhs), Value::Number(rhs)) => { let res = LuaNumber::from_bits(*lhs) > 0. || LuaNumber::from_bits(*rhs) > 0.; - Value::Number((res as u64 as f64).to_bits()) + Ok(Value::Number((res as u64 as f64).to_bits())) } (Value::Number(value), other) => { if LuaNumber::from_bits(*value) > 0. { - Value::Number(*value) + Ok(Value::Number(*value)) } else { - other.clone() + Ok(other.clone()) } } - (value, _) => value.clone(), - _ => Value::Nil, + (value, _) => Ok(value.clone()), + _ => Ok(Value::Nil), } } } @@ -210,7 +241,7 @@ impl Debug for Value { } pub trait RustFunction: Debug { - fn execute(&self, parameters: Vec) -> Vec; + fn execute(&self, parameters: Vec) -> Result, RuntimeError>; } #[derive(Debug, Clone)] @@ -276,29 +307,34 @@ impl ClosureRunner { } } - pub fn next(&mut self) -> Option> { + pub fn next(&mut self) -> Result>, RuntimeError> { if let Some(inner) = &mut self.inner { - if let Some(ret_values) = inner.next() { - self.inner = None; - if self.return_registers.len() == 0 { - for (i, value) in ret_values.iter().enumerate() { - self.stack.insert( - self.function_register + i as u16 + 1, - Rc::new(RefCell::new(value.clone())), - ); + match inner.next() { + Ok(ret_values) => { + if let Some(ret_values) = ret_values { + self.inner = None; + if self.return_registers.len() == 0 { + for (i, value) in ret_values.iter().enumerate() { + self.stack.insert( + self.function_register + i as u16 + 1, + Rc::new(RefCell::new(value.clone())), + ); + } + self.top = self.function_register + ret_values.len() as u16; + } + for (i, reg) in self.return_registers.iter().enumerate() { + self.stack.insert( + *reg, + Rc::new(RefCell::new( + ret_values.get(i).cloned().unwrap_or(Value::Nil), + )), + ); + } + } else { + return Ok(None); } - self.top = self.function_register + ret_values.len() as u16; } - for (i, reg) in self.return_registers.iter().enumerate() { - self.stack.insert( - *reg, - Rc::new(RefCell::new( - ret_values.get(i).cloned().unwrap_or(Value::Nil), - )), - ); - } - } else { - return None; + Err(e) => return Err(e), } } @@ -429,7 +465,7 @@ impl ClosureRunner { .unwrap_or(Value::Nil); match value { Value::RustFunction(func) => { - let ret_values = func.borrow_mut().execute(params); + let ret_values = func.borrow_mut().execute(params)?; if *ret_len != 0 { for i in 0..=(*ret_len - 2) { self.set_stack( @@ -507,7 +543,7 @@ impl ClosureRunner { .unwrap_or(Value::Nil), ); } - return Some(ret_values); + return Ok(Some(ret_values)); } Instruction::Add(res, lhs, rhs) => { let lhs = self @@ -520,7 +556,7 @@ impl ClosureRunner { .get(rhs) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - self.set_stack(*res, lhs.add(&rhs)); + self.set_stack(*res, lhs.add(&rhs)?); } Instruction::Equal(res, lhs, rhs) => { let lhs = self @@ -533,7 +569,7 @@ impl ClosureRunner { .get(rhs) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - self.set_stack(*res, lhs.eq(&rhs)); + self.set_stack(*res, lhs.eq(&rhs)?); } Instruction::LessThan(res, lhs, rhs) => { let lhs = self @@ -546,7 +582,7 @@ impl ClosureRunner { .get(rhs) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - self.set_stack(*res, lhs.lt(&rhs)); + self.set_stack(*res, lhs.lt(&rhs)?); } Instruction::LessThanOrEqual(res, lhs, rhs) => { let lhs = self @@ -559,7 +595,7 @@ impl ClosureRunner { .get(rhs) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - self.set_stack(*res, lhs.lte(&rhs)); + self.set_stack(*res, lhs.lte(&rhs)?); } Instruction::Unm(res, reg) => { self.set_stack( @@ -568,7 +604,7 @@ impl ClosureRunner { .get(reg) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil) - .unm(), + .unm()?, ); } Instruction::Or(res, lhs, rhs) => { @@ -582,7 +618,7 @@ impl ClosureRunner { .get(rhs) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - self.set_stack(*res, lhs.or(&rhs)); + self.set_stack(*res, lhs.or(&rhs)?); } Instruction::And(res, lhs, rhs) => { let lhs = self @@ -595,15 +631,15 @@ impl ClosureRunner { .get(rhs) .map(|v| v.borrow().clone()) .unwrap_or(Value::Nil); - self.set_stack(*res, lhs.and(&rhs)); + self.set_stack(*res, lhs.and(&rhs)?); } }; self.program_counter += 1; - None + Ok(None) } else { - Some(Vec::new()) + Ok(Some(Vec::new())) } } }