diff options
Diffstat (limited to 'src/interpret/value.rs')
| -rw-r--r-- | src/interpret/value.rs | 103 |
1 files changed, 67 insertions, 36 deletions
diff --git a/src/interpret/value.rs b/src/interpret/value.rs index 27f2668..86fe094 100644 --- a/src/interpret/value.rs +++ b/src/interpret/value.rs @@ -1,6 +1,6 @@ use crate::parse::ast::nodes::FnNode; -use anyhow::{anyhow, Result}; use std::{cell::RefCell, fmt::Display, rc::Rc}; +use thiserror::Error; type Ref<T> = RefCell<Rc<T>>; @@ -15,79 +15,79 @@ pub enum Value { } impl Value { - pub fn add(self, rhs: Value) -> Result<Value> { + pub fn add(self, rhs: Value) -> Result<Value, OperationError> { match self { - Value::Str(l) => match rhs { - Value::Str(r) => Ok(Value::Str(l + &r)), - Value::Float(r) => Ok(Value::Str(l + &r.to_string())), - Value::Int(r) => Ok(Value::Str(l + &r.to_string())), - _ => Err(anyhow!("Right operand can't be added.")), + Value::Str(ref l) => match rhs { + Value::Str(r) => Ok(Value::Str(format!("{}{}", l, r))), + Value::Float(r) => Ok(Value::Str(format!("{}{}", l, r))), + Value::Int(r) => Ok(Value::Str(format!("{}{}", l, r))), + r => Err(OperationError::AddTypes(self, r)), }, Value::Float(l) => match rhs { Value::Str(r) => Ok(Value::Str(l.to_string() + &r)), Value::Float(r) => Ok(Value::Float(l + r)), Value::Int(r) => Ok(Value::Float(l + r as f64)), - _ => Err(anyhow!("Right operand can't be added.")), + r => Err(OperationError::AddTypes(self, r)), }, Value::Int(l) => match rhs { Value::Str(r) => Ok(Value::Str(l.to_string() + &r)), Value::Float(r) => Ok(Value::Float(l as f64 + r)), Value::Int(r) => Ok(Value::Int(l + r)), - _ => Err(anyhow!("Right operand can't be added.")), + r => Err(OperationError::AddTypes(self, r)), }, - _ => Err(anyhow!("Left operand can't be added.")), + _ => Err(OperationError::AddTypes(self, rhs)), } } - pub fn sub(self, rhs: Value) -> Result<Value> { + pub fn sub(self, rhs: Value) -> Result<Value, OperationError> { match self { Value::Float(l) => match rhs { Value::Float(r) => Ok(Value::Float(l - r)), Value::Int(r) => Ok(Value::Float(l - r as f64)), - _ => Err(anyhow!("Right operand can't be substracted.")), + r => Err(OperationError::SubTypes(self, r)), }, Value::Int(l) => match rhs { Value::Float(r) => Ok(Value::Float(l as f64 - r)), Value::Int(r) => Ok(Value::Int(l - r)), - _ => Err(anyhow!("Right operand can't be substracted.")), + r => Err(OperationError::SubTypes(self, r)), }, - _ => Err(anyhow!("Left operand can't be substracted from.")), + _ => Err(OperationError::SubTypes(self, rhs)), } } - pub fn mul(self, rhs: Value) -> Result<Value> { + pub fn mul(self, rhs: Value) -> Result<Value, OperationError> { match self { Value::Float(l) => match rhs { Value::Float(r) => Ok(Value::Float(l * r)), Value::Int(r) => Ok(Value::Float(l * r as f64)), - _ => Err(anyhow!("Right operand can't be multiplied.")), + r => Err(OperationError::MulTypes(self, r)), }, Value::Int(l) => match rhs { Value::Float(r) => Ok(Value::Float(l as f64 * r)), Value::Int(r) => Ok(Value::Int(l * r)), - _ => Err(anyhow!("Right operand can't be multiplied.")), + r => Err(OperationError::MulTypes(self, r)), }, - _ => Err(anyhow!("Left operand can't be multiplied.")), + _ => Err(OperationError::MulTypes(self, rhs)), } } - pub fn div(self, rhs: Value) -> Result<Value> { + pub fn div(self, rhs: Value) -> Result<Value, OperationError> { match self { Value::Float(l) => match rhs { Value::Float(r) => Ok(Value::Float(l / r)), Value::Int(r) => Ok(Value::Float(l / r as f64)), - _ => Err(anyhow!("Right operand can't be multiplied.")), + r => Err(OperationError::DivTypes(self, r)), }, Value::Int(l) => match rhs { Value::Float(r) => Ok(Value::Float(l as f64 / r)), Value::Int(r) => Ok(Value::Float(l as f64 / r as f64)), - _ => Err(anyhow!("Right operand can't be multiplied.")), + r => Err(OperationError::DivTypes(self, r)), }, - _ => Err(anyhow!("Left operand can't be multiplied.")), + _ => Err(OperationError::DivTypes(self, rhs)), } } - pub fn eq(self, rhs: Value) -> Result<Value> { + pub fn eq(self, rhs: Value) -> Result<Value, OperationError> { match self { Value::Str(l) => match rhs { Value::Str(r) => Ok(Value::Bool(l == r)), @@ -109,7 +109,7 @@ impl Value { } } - pub fn neq(self, rhs: Value) -> Result<Value> { + pub fn neq(self, rhs: Value) -> Result<Value, OperationError> { if let Ok(Value::Bool(value)) = self.eq(rhs) { Ok(Value::Bool(!value)) } else { @@ -117,50 +117,63 @@ impl Value { } } - pub fn gt(self, rhs: Value) -> Result<Value> { + pub fn gt(self, rhs: Value) -> Result<Value, OperationError> { match self { Value::Float(r) => match rhs { Value::Float(l) => Ok(Value::Bool(r > l)), Value::Int(l) => Ok(Value::Bool(r > l as f64)), - _ => Err(anyhow!("Right operand can't be compared.")), + r => Err(OperationError::CompareTypes(self, r)), }, Value::Int(r) => match rhs { Value::Float(l) => Ok(Value::Bool(r as f64 > l)), Value::Int(l) => Ok(Value::Bool(r > l)), - _ => Err(anyhow!("Right operand can't be compared.")), + r => Err(OperationError::CompareTypes(self, r)), }, - _ => Err(anyhow!("Left operand can't be compared.")), + _ => Err(OperationError::CompareTypes(self, rhs)), } } - pub fn gte(self, rhs: Value) -> Result<Value> { + pub fn gte(self, rhs: Value) -> Result<Value, OperationError> { match self { Value::Float(r) => match rhs { Value::Float(l) => Ok(Value::Bool(r >= l)), Value::Int(l) => Ok(Value::Bool(r >= l as f64)), - _ => Err(anyhow!("Right operand can't be compared.")), + r => Err(OperationError::CompareTypes(self, r)), }, Value::Int(r) => match rhs { Value::Float(l) => Ok(Value::Bool(r as f64 >= l)), Value::Int(l) => Ok(Value::Bool(r >= l)), - _ => Err(anyhow!("Right operand can't be compared.")), + r => Err(OperationError::CompareTypes(self, r)), }, - _ => Err(anyhow!("Left operand can't be compared.")), + _ => Err(OperationError::CompareTypes(self, rhs)), } } - pub fn neg(self) -> Result<Value> { + pub fn neg(self) -> Result<Value, OperationError> { match self { Value::Float(float) => Ok(Value::Float(-float)), Value::Int(int) => Ok(Value::Int(-int)), - _ => Err(anyhow!("Can't negate value.")), + _ => Err(OperationError::NegType(self)), } } - pub fn not(self) -> Result<Value> { + pub fn not(self) -> Result<Value, OperationError> { match self { Value::Bool(bool) => Ok(Value::Bool(bool)), - _ => Err(anyhow!("Can't flip non-bool value.")), + _ => Err(OperationError::NotType(self)), + } + } +} + +impl Value { + pub fn type_name(&self) -> &'static str { + match self { + Value::Str(_) => "Str", + Value::Float(_) => "Float", + Value::Int(_) => "Int", + Value::Bool(_) => "Bool", + Value::Fn(_) => "Fn", + Value::Void => "Void", } } } @@ -177,3 +190,21 @@ impl Display for Value { } } } + +#[derive(Error, Debug)] +pub enum OperationError { + #[error("Can't add value '{0}' of type '{}' to value '{1}' of type '{}'.", .0.type_name(), .1.type_name())] + AddTypes(Value, Value), + #[error("Can't subtract value '{1}' of type '{}' from value '{0}' of type '{}'.", .1.type_name(), .0.type_name())] + SubTypes(Value, Value), + #[error("Can't multiply value '{0}' of type '{}' with value '{1}' of type '{}'.", .0.type_name(), .1.type_name())] + MulTypes(Value, Value), + #[error("Can't divide value '{0}' of type '{}' by value '{1}' of type '{}'.", .0.type_name(), .1.type_name())] + DivTypes(Value, Value), + #[error("Can't compare value '{0}' of type '{}' with value '{1}' of type '{}'.", .0.type_name(), .1.type_name())] + CompareTypes(Value, Value), + #[error("Can't negate value '{0}' of type '{}'.", .0.type_name())] + NegType(Value), + #[error("Can't flip value '{0}' of type '{}'.", .0.type_name())] + NotType(Value), +} |
