about summary refs log tree commit diff
path: root/src/interpret/value.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/interpret/value.rs')
-rw-r--r--src/interpret/value.rs103
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),
+}