mod display;
pub mod valuetype;
use self::valuetype::ValueType;
use super::out::*;
use crate::{settings::Rounding, token::tokentype::TokenType};
use num::complex::Complex64;
pub type IntValue = i64;
pub type FloatValue = f64;
pub type ComplexValue = Complex64;
pub type VectorValue = Vec<Value>;
pub type BoolValue = bool;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Value {
Int(IntValue),
Float(FloatValue),
Complex(ComplexValue),
Vector(VectorValue),
Bool(BoolValue),
}
impl Value {
pub fn get_type(&self) -> ValueType {
match self {
Value::Float(_) => ValueType::FloatType,
Value::Int(_) => ValueType::IntType,
Value::Complex(_) => ValueType::ComplexType,
Value::Vector(_) => ValueType::VectorType,
Value::Bool(_) => ValueType::BoolType,
}
}
pub fn is_int(&self) -> bool {
matches!(self, Value::Int(_))
}
pub fn is_float(&self) -> bool {
matches!(self, Value::Float(_))
}
pub fn is_complex(&self) -> bool {
matches!(self, Value::Complex(_))
}
pub fn is_vector(&self) -> bool {
matches!(self, Value::Vector(_))
}
pub fn is_bool(&self) -> bool {
matches!(self, Value::Bool(_))
}
pub fn as_int(&self) -> EvalResult<IntValue> {
match self {
Value::Int(n) => Ok(*n),
Value::Float(n) => {
if n.fract() == 0.0 {
Ok(*n as IntValue)
} else {
Err(ErrorType::FailedCast {
value: self.clone(),
from: ValueType::FloatType,
to: ValueType::IntType,
})
}
}
Value::Bool(n) => Ok(*n as i64),
_ => match self.as_float() {
Ok(float) => Value::Float(float).as_int(),
Err(err) => match err {
ErrorType::FailedCast { value, from, to: _ } => Err(ErrorType::FailedCast {
value,
from,
to: ValueType::IntType,
}),
other => Err(other),
},
},
}
}
pub fn as_float(&self) -> EvalResult<FloatValue> {
match self {
Value::Float(n) => Ok(*n),
Value::Int(n) => Ok(*n as f64),
Value::Bool(n) => Ok(*n as i64 as f64),
Value::Complex(n) => {
if n.im == 0.0 {
Ok(n.re)
} else {
Err(ErrorType::FailedCast {
value: self.clone(),
from: ValueType::ComplexType,
to: ValueType::FloatType,
})
}
}
_ => match self.as_complex() {
Ok(complex) => Value::Complex(complex).as_float(),
Err(err) => match err {
ErrorType::FailedCast { value, from, to: _ } => Err(ErrorType::FailedCast {
value,
from,
to: ValueType::FloatType,
}),
other => Err(other),
},
},
}
}
pub fn as_complex(&self) -> EvalResult<ComplexValue> {
match self {
Value::Complex(n) => Ok(*n),
Value::Float(n) => Ok(Complex64::new(*n, 0.0)),
Value::Int(n) => Ok(Complex64::new(*n as f64, 0.0)),
Value::Bool(n) => Ok(Complex64::new(*n as i64 as f64, 0.0)),
Value::Vector(v) => {
if v.len() == 1 {
v[0].as_complex()
} else {
Err(ErrorType::FailedCast {
value: self.clone(),
from: ValueType::VectorType,
to: ValueType::ComplexType,
})
}
}
}
}
pub fn as_vector(&self) -> VectorValue {
match self {
Value::Vector(v) => v.clone(),
Value::Int(n) => vec![Value::Int(*n)],
Value::Float(n) => vec![Value::Float(*n)],
Value::Complex(n) => vec![Value::Complex(*n)],
Value::Bool(n) => vec![Value::Bool(*n)],
}
}
pub fn as_bool(&self) -> EvalResult<BoolValue> {
match self {
Value::Bool(n) => Ok(*n),
Value::Int(n) => {
if *n == 1 {
Ok(true)
} else if *n == 0 {
Ok(false)
} else {
Err(ErrorType::FailedCast {
value: self.clone(),
from: ValueType::IntType,
to: ValueType::BoolType,
})
}
}
_ => match self.as_int() {
Ok(value) => Value::Int(value).as_bool(),
Err(err) => match err {
ErrorType::FailedCast { value, from, to: _ } => Err(ErrorType::FailedCast {
value,
from,
to: ValueType::BoolType,
}),
other => Err(other),
},
},
}
}
pub fn as_type(&self, valuetype: &ValueType) -> EvalResult<Value> {
match valuetype {
ValueType::BoolType => Ok(Value::Bool(self.as_bool()?)),
ValueType::IntType => Ok(Value::Int(self.as_int()?)),
ValueType::FloatType => Ok(Value::Float(self.as_float()?)),
ValueType::ComplexType => Ok(Value::Complex(self.as_complex()?)),
ValueType::VectorType => Ok(Value::Vector(self.as_vector())),
}
}
pub fn from_string(string: String) -> EvalResult<Self> {
match &string[..] {
"true" => Ok(Value::Bool(true)),
"false" => Ok(Value::Bool(false)),
other => {
let mut other = String::from(other);
let i_count = other.matches("i").count();
if i_count != 0 {
if i_count == 1 {
other = String::from(other).replace("i", "");
let other = if other == "" {
String::from("1")
} else {
other
};
return Ok(Value::Complex(Complex64::new(
0.0,
match other.parse::<f64>() {
Ok(value) => value,
Err(_) => return Err(ErrorType::FailedParse { value: string }),
},
)));
} else {
return Err(ErrorType::FailedParse { value: string });
}
}
let count = other.matches(".").count();
if count != 0 {
if count == 1 {
match other.parse::<f64>() {
Ok(value) => Ok(Value::Float(value)),
Err(_) => Err(ErrorType::FailedParse { value: string }),
}
} else {
Err(ErrorType::InvalidTokenPosition {
token: TokenType::Dot,
})
}
} else {
match other.parse::<i64>() {
Ok(value) => Ok(Value::Int(value)),
Err(_) => Err(ErrorType::FailedParse { value: string }),
}
}
}
}
}
pub fn try_as_type(&self, valuetype: ValueType) -> Value {
if self.to_type().complexity() <= valuetype.complexity() {
self.clone()
} else {
match valuetype {
ValueType::BoolType => match self.as_bool() {
Ok(value) => Value::Bool(value),
Err(_) => self.try_as_type(ValueType::IntType),
},
ValueType::IntType => match self.as_int() {
Ok(value) => Value::Int(value),
Err(_) => self.try_as_type(ValueType::FloatType),
},
ValueType::FloatType => match self.as_float() {
Ok(value) => Value::Float(value),
Err(_) => self.try_as_type(ValueType::ComplexType),
},
ValueType::ComplexType => match self.as_complex() {
Ok(value) => Value::Complex(value),
Err(_) => self.try_as_type(ValueType::VectorType),
},
ValueType::VectorType => Value::Vector(self.as_vector()),
}
}
}
pub fn round(&self, rounding: Rounding) -> Self {
match rounding {
Rounding::Round(precision) => {
let precision = precision.clamp(0, 12);
let factor = (10.0f64.powi(precision as i32)) as f64;
match self {
Self::Float(v) => Value::Float((*v * factor).round() / factor),
Self::Complex(c) => Value::Complex(Complex64::new(
(c.re * factor).round() / factor,
(c.im * factor).round() / factor,
)),
Self::Vector(vec) => {
let mut out_vec = vec![];
for val in vec {
out_vec.push(val.round(rounding).clone());
}
Value::Vector(out_vec)
}
other => other.clone(),
}
}
_ => self.clone(),
}
}
}
impl From<BoolValue> for Value {
fn from(bool: BoolValue) -> Self {
Value::Bool(bool)
}
}
impl From<IntValue> for Value {
fn from(int: IntValue) -> Self {
Value::Int(int)
}
}
impl From<FloatValue> for Value {
fn from(float: FloatValue) -> Self {
Value::Float(float)
}
}
impl From<ComplexValue> for Value {
fn from(complex: ComplexValue) -> Self {
Value::Complex(complex)
}
}
impl<T> From<Vec<T>> for Value
where
Value: From<T>,
T: Clone,
{
fn from(vec: Vec<T>) -> Self {
Value::Vector(vec.iter().map(|v| Value::from(v.clone())).collect())
}
}
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match self.clone().equal_to(other.clone()) {
Ok(bool_value) => bool_value.as_bool().unwrap(),
Err(_) => false,
}
}
}