2024-08-09 01:59:09 +00:00
|
|
|
//! Dust value representation
|
2024-02-25 18:49:26 +00:00
|
|
|
use std::{
|
2024-02-25 19:26:22 +00:00
|
|
|
cmp::Ordering,
|
2024-08-10 01:12:36 +00:00
|
|
|
collections::BTreeMap,
|
2024-08-09 00:58:56 +00:00
|
|
|
error::Error,
|
2024-03-06 20:36:58 +00:00
|
|
|
fmt::{self, Display, Formatter},
|
2024-02-25 18:49:26 +00:00
|
|
|
ops::Range,
|
2024-08-16 03:17:49 +00:00
|
|
|
sync::{Arc, RwLock, RwLockWriteGuard},
|
2024-02-25 18:49:26 +00:00
|
|
|
};
|
|
|
|
|
2024-06-19 07:32:51 +00:00
|
|
|
use serde::{
|
|
|
|
de::Visitor,
|
2024-08-04 00:23:52 +00:00
|
|
|
ser::{SerializeMap, SerializeSeq, SerializeTuple},
|
2024-08-14 05:03:46 +00:00
|
|
|
Deserialize, Deserializer, Serialize, Serializer,
|
2024-06-19 07:32:51 +00:00
|
|
|
};
|
2024-06-04 18:47:15 +00:00
|
|
|
|
2024-08-13 19:12:32 +00:00
|
|
|
use crate::{AbstractSyntaxTree, Context, Identifier, StructType, Type, Vm, VmError};
|
2024-02-25 18:49:26 +00:00
|
|
|
|
2024-08-07 23:12:40 +00:00
|
|
|
/// Dust value representation
|
|
|
|
///
|
|
|
|
/// Each type of value has a corresponding constructor, here are some simple examples:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # use dust_lang::Value;
|
|
|
|
/// let boolean = Value::boolean(true);
|
|
|
|
/// let float = Value::float(3.14);
|
|
|
|
/// let integer = Value::integer(42);
|
|
|
|
/// let string = Value::string("Hello, world!");
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Values can be combined into more complex values:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # use dust_lang::Value;
|
|
|
|
/// let list = Value::list(vec![
|
|
|
|
/// Value::integer(1),
|
|
|
|
/// Value::integer(2),
|
|
|
|
/// Value::integer(3),
|
|
|
|
/// ]);
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Values have a type, which can be retrieved using the `type` method:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # use std::collections::HashMap;
|
2024-08-10 08:32:27 +00:00
|
|
|
/// # use dust_lang::*;
|
2024-08-07 23:12:40 +00:00
|
|
|
/// let value = Value::integer(42);
|
|
|
|
///
|
2024-08-13 16:23:25 +00:00
|
|
|
/// assert_eq!(value.r#type(), Type::Integer);
|
2024-08-07 23:12:40 +00:00
|
|
|
/// ```
|
2024-08-14 05:03:46 +00:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum Value {
|
|
|
|
Immutable(Arc<ValueData>),
|
|
|
|
Mutable(Arc<RwLock<ValueData>>),
|
|
|
|
}
|
2024-02-25 18:49:26 +00:00
|
|
|
|
|
|
|
impl Value {
|
|
|
|
pub fn boolean(boolean: bool) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::Boolean(boolean)))
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn float(float: f64) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::Float(float)))
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 22:24:25 +00:00
|
|
|
pub fn function(function: Function) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::Function(function)))
|
2024-08-07 22:24:25 +00:00
|
|
|
}
|
|
|
|
|
2024-02-25 18:49:26 +00:00
|
|
|
pub fn integer(integer: i64) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::Integer(integer)))
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-06-19 08:56:56 +00:00
|
|
|
pub fn list(list: Vec<Value>) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::List(list)))
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-02-28 23:36:47 +00:00
|
|
|
pub fn map(map: BTreeMap<Identifier, Value>) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::Map(map)))
|
2024-02-28 23:36:47 +00:00
|
|
|
}
|
2024-02-25 18:49:26 +00:00
|
|
|
|
|
|
|
pub fn range(range: Range<i64>) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::Range(range)))
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-03-24 14:58:09 +00:00
|
|
|
pub fn string<T: ToString>(to_string: T) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::String(to_string.to_string())))
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 17:28:22 +00:00
|
|
|
pub fn r#struct(r#struct: Struct) -> Self {
|
2024-08-14 05:03:46 +00:00
|
|
|
Value::Immutable(Arc::new(ValueData::Struct(r#struct)))
|
2024-08-13 17:28:22 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 05:13:43 +00:00
|
|
|
pub fn boolean_mut(boolean: bool) -> Self {
|
|
|
|
Value::Mutable(Arc::new(RwLock::new(ValueData::Boolean(boolean))))
|
|
|
|
}
|
|
|
|
|
2024-08-14 08:59:27 +00:00
|
|
|
pub fn string_mut<T: ToString>(to_string: T) -> Self {
|
|
|
|
Value::Mutable(Arc::new(RwLock::new(ValueData::String(
|
|
|
|
to_string.to_string(),
|
|
|
|
))))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_mutable(&self) -> bool {
|
|
|
|
matches!(self, Value::Mutable(_))
|
|
|
|
}
|
|
|
|
|
2024-08-16 13:22:36 +00:00
|
|
|
pub fn to_mut(self) -> Result<Value, ValueError> {
|
|
|
|
if let Value::Immutable(arc) = self {
|
|
|
|
let value_data = if let Some(value_data) = Arc::into_inner(arc) {
|
|
|
|
value_data
|
|
|
|
} else {
|
|
|
|
return Err(ValueError::CannotMakeMutable);
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(Value::Mutable(Arc::new(RwLock::new(value_data))))
|
|
|
|
} else {
|
|
|
|
Ok(self)
|
2024-08-14 07:53:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-16 10:43:29 +00:00
|
|
|
pub fn mutate(&self, other: Value) -> Result<(), ValueError> {
|
|
|
|
let mut inner = match self {
|
|
|
|
Value::Immutable(_) => return Err(ValueError::CannotMutate(self.clone())),
|
|
|
|
Value::Mutable(inner) => inner.write().unwrap(),
|
2024-08-14 07:53:15 +00:00
|
|
|
};
|
|
|
|
|
2024-08-16 10:43:29 +00:00
|
|
|
match other {
|
|
|
|
Value::Immutable(other) => *inner = other.as_ref().clone(),
|
|
|
|
Value::Mutable(other) => *inner = other.read().unwrap().clone(),
|
2024-08-14 07:53:15 +00:00
|
|
|
}
|
2024-08-16 10:43:29 +00:00
|
|
|
|
|
|
|
Ok(())
|
2024-08-14 07:53:15 +00:00
|
|
|
}
|
|
|
|
|
2024-08-13 16:23:25 +00:00
|
|
|
pub fn r#type(&self) -> Type {
|
2024-08-14 05:03:46 +00:00
|
|
|
match self {
|
|
|
|
Value::Immutable(inner) => inner.r#type(),
|
|
|
|
Value::Mutable(inner_locked) => inner_locked.read().unwrap().r#type(),
|
|
|
|
}
|
2024-03-06 22:32:31 +00:00
|
|
|
}
|
|
|
|
|
2024-03-17 20:59:52 +00:00
|
|
|
pub fn as_boolean(&self) -> Option<bool> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match self {
|
|
|
|
Value::Immutable(arc) => match arc.as_ref() {
|
|
|
|
ValueData::Boolean(boolean) => Some(*boolean),
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
Value::Mutable(arc_rw_lock) => match *arc_rw_lock.read().unwrap() {
|
|
|
|
ValueData::Boolean(boolean) => Some(boolean),
|
|
|
|
_ => None,
|
|
|
|
},
|
2024-03-09 13:10:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-12 09:44:05 +00:00
|
|
|
pub fn as_float(&self) -> Option<f64> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match self {
|
|
|
|
Value::Immutable(arc) => match arc.as_ref() {
|
|
|
|
ValueData::Float(float) => Some(*float),
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
Value::Mutable(arc_rw_lock) => match *arc_rw_lock.read().unwrap() {
|
|
|
|
ValueData::Float(float) => Some(float),
|
|
|
|
_ => None,
|
|
|
|
},
|
2024-08-12 09:44:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-07 22:24:25 +00:00
|
|
|
pub fn as_function(&self) -> Option<&Function> {
|
2024-08-14 05:03:46 +00:00
|
|
|
if let Value::Immutable(arc) = self {
|
|
|
|
if let ValueData::Function(function) = arc.as_ref() {
|
|
|
|
return Some(function);
|
|
|
|
}
|
2024-08-07 22:24:25 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
None
|
2024-08-07 22:24:25 +00:00
|
|
|
}
|
|
|
|
|
2024-06-19 08:56:56 +00:00
|
|
|
pub fn as_list(&self) -> Option<&Vec<Value>> {
|
2024-08-14 05:03:46 +00:00
|
|
|
if let Value::Immutable(arc) = self {
|
|
|
|
if let ValueData::List(list) = arc.as_ref() {
|
|
|
|
return Some(list);
|
|
|
|
}
|
2024-03-07 17:29:07 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
None
|
2024-03-07 17:29:07 +00:00
|
|
|
}
|
|
|
|
|
2024-08-12 02:02:17 +00:00
|
|
|
pub fn as_map(&self) -> Option<&BTreeMap<Identifier, Value>> {
|
2024-08-14 05:03:46 +00:00
|
|
|
if let Value::Immutable(arc) = self {
|
|
|
|
if let ValueData::Map(map) = arc.as_ref() {
|
|
|
|
return Some(map);
|
|
|
|
}
|
2024-08-12 02:02:17 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
None
|
2024-08-12 02:02:17 +00:00
|
|
|
}
|
|
|
|
|
2024-03-07 17:29:07 +00:00
|
|
|
pub fn as_integer(&self) -> Option<i64> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match self {
|
|
|
|
Value::Immutable(arc) => match arc.as_ref() {
|
|
|
|
ValueData::Integer(integer) => Some(*integer),
|
|
|
|
_ => None,
|
|
|
|
},
|
|
|
|
Value::Mutable(arc_rw_lock) => match *arc_rw_lock.read().unwrap() {
|
|
|
|
ValueData::Integer(integer) => Some(integer),
|
|
|
|
_ => None,
|
|
|
|
},
|
2024-03-07 17:29:07 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-05 02:15:31 +00:00
|
|
|
|
2024-08-16 03:17:49 +00:00
|
|
|
pub fn as_string(&self) -> Option<&String> {
|
2024-08-14 05:03:46 +00:00
|
|
|
if let Value::Immutable(arc) = self {
|
2024-08-16 03:17:49 +00:00
|
|
|
if let ValueData::String(string) = arc.as_ref() {
|
|
|
|
return Some(string);
|
2024-08-14 05:03:46 +00:00
|
|
|
}
|
2024-08-12 14:43:18 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
None
|
2024-08-12 14:43:18 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 03:17:49 +00:00
|
|
|
pub fn as_struct(&self) -> Option<&Struct> {
|
2024-08-14 05:03:46 +00:00
|
|
|
if let Value::Immutable(arc) = self {
|
2024-08-16 03:17:49 +00:00
|
|
|
if let ValueData::Struct(r#struct) = arc.as_ref() {
|
|
|
|
return Some(r#struct);
|
2024-08-14 05:03:46 +00:00
|
|
|
}
|
2024-08-12 15:24:24 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
None
|
2024-08-12 15:24:24 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 03:17:49 +00:00
|
|
|
pub fn value_data_immutable(&self) -> Option<&ValueData> {
|
|
|
|
if let Value::Immutable(inner) = self {
|
|
|
|
Some(inner.as_ref())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn value_data_mutable(&self) -> Option<RwLockWriteGuard<ValueData>> {
|
|
|
|
if let Value::Mutable(inner) = self {
|
|
|
|
Some(inner.write().unwrap())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_field(&self, field: &Identifier) -> Option<Value> {
|
2024-08-16 09:14:00 +00:00
|
|
|
match self {
|
2024-08-16 03:17:49 +00:00
|
|
|
Value::Immutable(inner) => inner.get_field(field),
|
|
|
|
Value::Mutable(inner) => inner.read().unwrap().get_field(field),
|
2024-08-16 09:14:00 +00:00
|
|
|
}
|
2024-08-16 03:17:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_index(&self, index: usize) -> Option<Value> {
|
2024-08-16 09:14:00 +00:00
|
|
|
match self {
|
2024-08-16 03:17:49 +00:00
|
|
|
Value::Immutable(inner) => inner.get_index(index),
|
|
|
|
Value::Mutable(inner) => inner.read().unwrap().get_index(index),
|
2024-08-16 09:14:00 +00:00
|
|
|
}
|
2024-08-16 03:17:49 +00:00
|
|
|
}
|
|
|
|
|
2024-08-05 02:15:31 +00:00
|
|
|
pub fn add(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left + right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_add(*right)));
|
|
|
|
}
|
|
|
|
(ValueData::String(left), ValueData::String(right)) => {
|
|
|
|
return Ok(Value::string(left.to_string() + right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left + right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_add(*right)));
|
|
|
|
}
|
|
|
|
(ValueData::String(left), ValueData::String(right)) => {
|
|
|
|
return Ok(Value::string(left.to_string() + right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-05 02:15:31 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
(Value::Immutable(left), Value::Mutable(right)) => {
|
2024-08-14 08:59:27 +00:00
|
|
|
match (left.as_ref(), &*right.read().unwrap()) {
|
2024-08-14 05:03:46 +00:00
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left + right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_add(*right)));
|
|
|
|
}
|
|
|
|
(ValueData::String(left), ValueData::String(right)) => {
|
|
|
|
return Ok(Value::string(left.to_string() + right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left + right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_add(*right)));
|
|
|
|
}
|
|
|
|
(ValueData::String(left), ValueData::String(right)) => {
|
|
|
|
return Ok(Value::string(left.to_string() + right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 04:49:17 +00:00
|
|
|
}
|
2024-08-05 02:15:31 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotAdd(self.clone(), other.clone()))
|
2024-08-05 02:15:31 +00:00
|
|
|
}
|
2024-08-09 03:28:47 +00:00
|
|
|
|
2024-08-16 13:22:36 +00:00
|
|
|
pub fn add_assign(&self, other: &Value) -> Result<(), ValueError> {
|
2024-08-14 08:59:27 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
*left += right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
*left = left.saturating_add(*right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::String(left), ValueData::String(right)) => {
|
|
|
|
left.push_str(right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
*left += right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
*left = left.saturating_add(*right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::String(left), ValueData::String(right)) => {
|
|
|
|
left.push_str(right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(_), _) => {
|
|
|
|
return Err(ValueError::CannotMutate(self.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(ValueError::CannotAdd(self.clone(), other.clone()))
|
|
|
|
}
|
|
|
|
|
2024-08-09 03:28:47 +00:00
|
|
|
pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left - right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_sub(*right)));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left - right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_sub(*right)));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(left), Value::Mutable(right)) => {
|
|
|
|
match (left.as_ref(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left - right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_sub(*right)));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(right), Value::Immutable(left)) => {
|
|
|
|
match (&*right.read().unwrap(), left.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left - right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_sub(*right)));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 03:28:47 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotSubtract(self.clone(), other.clone()))
|
2024-08-09 03:28:47 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 13:22:36 +00:00
|
|
|
pub fn subtract_assign(&self, other: &Value) -> Result<(), ValueError> {
|
2024-08-14 18:28:39 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
*left -= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
*left = left.saturating_sub(*right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
*left -= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
*left = left.saturating_sub(*right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(_), _) => {
|
|
|
|
return Err(ValueError::CannotMutate(self.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(ValueError::CannotSubtract(self.clone(), other.clone()))
|
|
|
|
}
|
|
|
|
|
2024-08-09 03:28:47 +00:00
|
|
|
pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left * right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_mul(*right)));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left * right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_mul(*right)));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(data), Value::Mutable(data_locked))
|
|
|
|
| (Value::Mutable(data_locked), Value::Immutable(data)) => {
|
|
|
|
match (&*data_locked.read().unwrap(), data.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left * right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::integer(left.saturating_mul(*right)));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 03:28:47 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotMultiply(self.clone(), other.clone()))
|
2024-08-09 03:28:47 +00:00
|
|
|
}
|
2024-08-09 07:00:48 +00:00
|
|
|
|
2024-08-16 13:22:36 +00:00
|
|
|
pub fn multiply_assign(&self, other: &Value) -> Result<(), ValueError> {
|
|
|
|
match (self, other) {
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
*left *= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
*left = left.saturating_mul(*right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
*left *= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
*left = left.saturating_mul(*right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(_), _) => {
|
|
|
|
return Err(ValueError::CannotMutate(self.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(ValueError::CannotMultiply(self.clone(), other.clone()))
|
|
|
|
}
|
|
|
|
|
2024-08-09 10:46:24 +00:00
|
|
|
pub fn divide(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
if *right == 0.0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::float(left / right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::integer(left / right));
|
|
|
|
}
|
|
|
|
_ => {}
|
2024-08-09 10:46:24 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
if *right == 0.0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::float(left / right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::integer(left / right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(left), Value::Mutable(right)) => {
|
|
|
|
match (left.as_ref(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
if *right == 0.0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::float(left / right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::integer(left / right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
if *right == 0.0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::float(left / right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::integer(left / right));
|
|
|
|
}
|
|
|
|
_ => {}
|
2024-08-09 10:46:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotDivide(self.clone(), other.clone()))
|
2024-08-09 10:46:24 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 13:22:36 +00:00
|
|
|
pub fn divide_assign(&self, other: &Value) -> Result<(), ValueError> {
|
|
|
|
match (self, other) {
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
if *right == 0.0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
*left /= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
*left = left.saturating_div(*right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
if *right == 0.0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
*left /= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
*left = left.saturating_div(*right);
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(_), _) => {
|
|
|
|
return Err(ValueError::CannotMutate(self.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(ValueError::CannotDivide(self.clone(), other.clone()))
|
|
|
|
}
|
|
|
|
|
2024-08-09 11:02:55 +00:00
|
|
|
pub fn modulo(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left % right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::integer(left % right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left % right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::integer(left % right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(left), Value::Mutable(right)) => {
|
|
|
|
match (left.as_ref(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left % right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::integer(left % right));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::float(left % right));
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
return Ok(Value::integer(left % right));
|
|
|
|
}
|
|
|
|
_ => {}
|
2024-08-09 11:02:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotModulo(self.clone(), other.clone()))
|
2024-08-09 11:02:55 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 13:22:36 +00:00
|
|
|
pub fn modulo_assign(&self, other: &Value) -> Result<(), ValueError> {
|
|
|
|
match (self, other) {
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
*left %= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
*left %= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&mut *left.write().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
*left %= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
if *right == 0 {
|
|
|
|
return Err(ValueError::DivisionByZero);
|
|
|
|
}
|
|
|
|
*left %= right;
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(_), _) => {
|
|
|
|
return Err(ValueError::CannotMutate(self.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(ValueError::CannotModulo(self.clone(), other.clone()))
|
|
|
|
}
|
|
|
|
|
2024-08-16 10:43:29 +00:00
|
|
|
pub fn equal(&self, other: &Value) -> Value {
|
|
|
|
let is_equal = match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => left == right,
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
*left.read().unwrap() == *right.read().unwrap()
|
|
|
|
}
|
|
|
|
(Value::Immutable(arc), Value::Mutable(arc_locked))
|
|
|
|
| (Value::Mutable(arc_locked), Value::Immutable(arc)) => {
|
|
|
|
*arc_locked.read().unwrap() == *arc.as_ref()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Value::boolean(is_equal)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn not_equal(&self, other: &Value) -> Value {
|
|
|
|
let is_not_equal = match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => left != right,
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
*left.read().unwrap() != *right.read().unwrap()
|
|
|
|
}
|
|
|
|
(Value::Immutable(arc), Value::Mutable(arc_locked))
|
|
|
|
| (Value::Mutable(arc_locked), Value::Immutable(arc)) => {
|
|
|
|
*arc_locked.read().unwrap() != *arc.as_ref()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Value::boolean(is_not_equal)
|
|
|
|
}
|
|
|
|
|
2024-08-09 07:00:48 +00:00
|
|
|
pub fn less_than(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left < right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left < right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left < right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left < right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(left), Value::Mutable(right)) => {
|
|
|
|
match (left.as_ref(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left < right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left < right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left < right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left < right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotLessThan(self.clone(), other.clone()))
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn less_than_or_equal(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left <= right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left <= right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left <= right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left <= right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
(Value::Immutable(left), Value::Mutable(right)) => {
|
|
|
|
match (left.as_ref(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left <= right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left <= right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left <= right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left <= right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotLessThanOrEqual(
|
|
|
|
self.clone(),
|
|
|
|
other.clone(),
|
|
|
|
))
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn greater_than(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left > right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left > right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left > right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left > right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Immutable(left), Value::Mutable(right)) => {
|
|
|
|
match (left.as_ref(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left > right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left > right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left > right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left > right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotGreaterThan(self.clone(), other.clone()))
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn greater_than_or_equal(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
match (left.as_ref(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left >= right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left >= right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left >= right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left >= right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
(Value::Immutable(left), Value::Mutable(right)) => {
|
|
|
|
match (left.as_ref(), &*right.read().unwrap()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left >= right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left >= right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Immutable(right)) => {
|
|
|
|
match (&*left.read().unwrap(), right.as_ref()) {
|
|
|
|
(ValueData::Float(left), ValueData::Float(right)) => {
|
|
|
|
return Ok(Value::boolean(left >= right))
|
|
|
|
}
|
|
|
|
(ValueData::Integer(left), ValueData::Integer(right)) => {
|
|
|
|
return Ok(Value::boolean(left >= right))
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotGreaterThanOrEqual(
|
|
|
|
self.clone(),
|
|
|
|
other.clone(),
|
|
|
|
))
|
2024-08-09 07:00:48 +00:00
|
|
|
}
|
2024-08-09 08:56:24 +00:00
|
|
|
|
|
|
|
pub fn and(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
if let (ValueData::Boolean(left), ValueData::Boolean(right)) =
|
|
|
|
(left.as_ref(), right.as_ref())
|
|
|
|
{
|
|
|
|
return Ok(Value::boolean(*left && *right));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
if let (ValueData::Boolean(left), ValueData::Boolean(right)) =
|
|
|
|
(&*left.read().unwrap(), &*right.read().unwrap())
|
|
|
|
{
|
|
|
|
return Ok(Value::boolean(*left && *right));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(locked), Value::Immutable(data))
|
|
|
|
| (Value::Immutable(data), Value::Mutable(locked)) => {
|
|
|
|
if let (ValueData::Boolean(left), ValueData::Boolean(right)) =
|
|
|
|
(&*locked.read().unwrap(), data.as_ref())
|
|
|
|
{
|
|
|
|
return Ok(Value::boolean(*left && *right));
|
|
|
|
}
|
2024-08-09 08:56:24 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotAnd(self.clone(), other.clone()))
|
2024-08-09 08:56:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn or(&self, other: &Value) -> Result<Value, ValueError> {
|
2024-08-14 05:03:46 +00:00
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => {
|
|
|
|
if let (ValueData::Boolean(left), ValueData::Boolean(right)) =
|
|
|
|
(left.as_ref(), right.as_ref())
|
|
|
|
{
|
|
|
|
return Ok(Value::boolean(*left || *right));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
if let (ValueData::Boolean(left), ValueData::Boolean(right)) =
|
|
|
|
(&*left.read().unwrap(), &*right.read().unwrap())
|
|
|
|
{
|
|
|
|
return Ok(Value::boolean(*left || *right));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Value::Mutable(locked), Value::Immutable(data))
|
|
|
|
| (Value::Immutable(data), Value::Mutable(locked)) => {
|
|
|
|
if let (ValueData::Boolean(left), ValueData::Boolean(right)) =
|
|
|
|
(&*locked.read().unwrap(), data.as_ref())
|
|
|
|
{
|
|
|
|
return Ok(Value::boolean(*left || *right));
|
|
|
|
}
|
2024-08-09 08:56:24 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
|
|
|
|
Err(ValueError::CannotOr(self.clone(), other.clone()))
|
2024-08-09 08:56:24 +00:00
|
|
|
}
|
2024-03-06 20:36:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Value {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
2024-08-14 05:03:46 +00:00
|
|
|
match self {
|
|
|
|
Value::Immutable(inner) => write!(f, "{inner}"),
|
|
|
|
Value::Mutable(inner_locked) => {
|
|
|
|
let inner = inner_locked.read().unwrap();
|
|
|
|
|
|
|
|
write!(f, "{inner}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for Value {}
|
|
|
|
|
|
|
|
impl PartialEq for Value {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => left == right,
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
*left.read().unwrap() == *right.read().unwrap()
|
|
|
|
}
|
|
|
|
(Value::Immutable(inner), Value::Mutable(inner_locked))
|
|
|
|
| (Value::Mutable(inner_locked), Value::Immutable(inner)) => {
|
|
|
|
**inner == *inner_locked.read().unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for Value {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ord for Value {
|
|
|
|
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
|
|
match (self, other) {
|
|
|
|
(Value::Immutable(left), Value::Immutable(right)) => left.cmp(right),
|
|
|
|
(Value::Mutable(left), Value::Mutable(right)) => {
|
|
|
|
left.read().unwrap().cmp(&right.read().unwrap())
|
|
|
|
}
|
|
|
|
(Value::Immutable(inner), Value::Mutable(inner_locked))
|
|
|
|
| (Value::Mutable(inner_locked), Value::Immutable(inner)) => {
|
|
|
|
inner_locked.read().unwrap().cmp(inner)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Serialize for Value {
|
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: Serializer,
|
|
|
|
{
|
|
|
|
match self {
|
|
|
|
Value::Immutable(inner) => inner.serialize(serializer),
|
|
|
|
Value::Mutable(inner_locked) => inner_locked.read().unwrap().serialize(serializer),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'de> Deserialize<'de> for Value {
|
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
|
|
|
|
where
|
|
|
|
D: Deserializer<'de>,
|
|
|
|
{
|
|
|
|
ValueData::deserialize(deserializer).map(|data| Value::Immutable(Arc::new(data)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum ValueData {
|
|
|
|
Boolean(bool),
|
|
|
|
Float(f64),
|
|
|
|
Function(Function),
|
|
|
|
Integer(i64),
|
|
|
|
List(Vec<Value>),
|
|
|
|
Map(BTreeMap<Identifier, Value>),
|
|
|
|
Range(Range<i64>),
|
|
|
|
String(String),
|
|
|
|
Struct(Struct),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ValueData {
|
|
|
|
fn r#type(&self) -> Type {
|
|
|
|
match self {
|
|
|
|
ValueData::Boolean(_) => Type::Boolean,
|
|
|
|
ValueData::Float(_) => Type::Float,
|
|
|
|
ValueData::Function(function) => Type::Function {
|
|
|
|
type_parameters: function.type_parameters.clone(),
|
|
|
|
value_parameters: function.value_parameters.clone(),
|
|
|
|
return_type: function.return_type.as_ref().cloned().map(Box::new),
|
|
|
|
},
|
|
|
|
ValueData::Integer(_) => Type::Integer,
|
|
|
|
ValueData::List(values) => {
|
|
|
|
let item_type = values.first().unwrap().r#type();
|
|
|
|
|
|
|
|
Type::List {
|
|
|
|
item_type: Box::new(item_type),
|
|
|
|
length: values.len(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ValueData::Map(value_map) => {
|
|
|
|
let mut type_map = BTreeMap::new();
|
|
|
|
|
|
|
|
for (identifier, value) in value_map {
|
|
|
|
let r#type = value.r#type();
|
|
|
|
|
|
|
|
type_map.insert(identifier.clone(), r#type);
|
|
|
|
}
|
|
|
|
|
|
|
|
Type::Map(type_map)
|
|
|
|
}
|
|
|
|
ValueData::Range(_) => Type::Range,
|
|
|
|
ValueData::String(_) => Type::String,
|
|
|
|
ValueData::Struct(r#struct) => match r#struct {
|
|
|
|
Struct::Unit { name } => Type::Struct(StructType::Unit { name: name.clone() }),
|
|
|
|
Struct::Tuple { .. } => todo!(),
|
|
|
|
Struct::Fields { .. } => todo!(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-16 03:17:49 +00:00
|
|
|
fn get_field(&self, property: &Identifier) -> Option<Value> {
|
|
|
|
if let ValueData::Struct(Struct::Fields { fields, .. }) = self {
|
|
|
|
fields.iter().find_map(|(identifier, value)| {
|
|
|
|
if identifier == property {
|
|
|
|
Some(value.clone())
|
2024-08-14 05:03:46 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2024-08-16 03:17:49 +00:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_index(&self, index: usize) -> Option<Value> {
|
|
|
|
if let ValueData::List(list) = self {
|
|
|
|
return list.get(index).cloned();
|
|
|
|
}
|
|
|
|
|
|
|
|
if let ValueData::Range(range) = self {
|
|
|
|
if range.contains(&(index as i64)) {
|
|
|
|
return Some(Value::integer(index as i64));
|
2024-08-14 05:03:46 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-16 03:17:49 +00:00
|
|
|
|
|
|
|
if let ValueData::String(string) = self {
|
|
|
|
return string
|
|
|
|
.chars()
|
|
|
|
.nth(index)
|
|
|
|
.map(|character| Value::string(character.to_string()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let ValueData::Struct(Struct::Tuple { fields, .. }) = self {
|
|
|
|
return fields.get(index).cloned();
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
2024-08-14 05:03:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for ValueData {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
ValueData::Boolean(boolean) => write!(f, "{boolean}"),
|
|
|
|
ValueData::Float(float) => {
|
2024-08-09 04:31:38 +00:00
|
|
|
if float == &f64::INFINITY {
|
|
|
|
return write!(f, "Infinity");
|
|
|
|
}
|
|
|
|
|
|
|
|
if float == &f64::NEG_INFINITY {
|
|
|
|
return write!(f, "-Infinity");
|
|
|
|
}
|
|
|
|
|
2024-06-24 18:44:10 +00:00
|
|
|
write!(f, "{float}")?;
|
|
|
|
|
|
|
|
if &float.floor() == float {
|
|
|
|
write!(f, ".0")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
ValueData::Function(function) => write!(f, "{function}"),
|
|
|
|
ValueData::Integer(integer) => write!(f, "{integer}"),
|
|
|
|
ValueData::List(list) => {
|
2024-04-22 05:51:34 +00:00
|
|
|
write!(f, "[")?;
|
2024-03-08 03:20:59 +00:00
|
|
|
|
2024-07-12 14:20:52 +00:00
|
|
|
for (index, value) in list.iter().enumerate() {
|
2024-04-22 05:51:34 +00:00
|
|
|
if index == list.len() - 1 {
|
2024-06-19 08:56:56 +00:00
|
|
|
write!(f, "{}", value)?;
|
2024-04-22 05:51:34 +00:00
|
|
|
} else {
|
2024-06-19 08:56:56 +00:00
|
|
|
write!(f, "{}, ", value)?;
|
2024-04-22 05:51:34 +00:00
|
|
|
}
|
2024-03-08 03:20:59 +00:00
|
|
|
}
|
|
|
|
|
2024-04-22 05:51:34 +00:00
|
|
|
write!(f, "]")
|
2024-03-08 03:20:59 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
ValueData::Map(map) => {
|
2024-06-24 08:16:05 +00:00
|
|
|
write!(f, "{{ ")?;
|
|
|
|
|
2024-07-12 14:20:52 +00:00
|
|
|
for (index, (key, value)) in map.iter().enumerate() {
|
2024-06-26 18:21:55 +00:00
|
|
|
write!(f, "{key} = {value}")?;
|
2024-03-07 21:19:24 +00:00
|
|
|
|
2024-06-24 08:16:05 +00:00
|
|
|
if index != map.len() - 1 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
2024-03-07 21:19:24 +00:00
|
|
|
}
|
|
|
|
|
2024-06-24 08:16:05 +00:00
|
|
|
write!(f, " }}")
|
2024-03-07 21:19:24 +00:00
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
ValueData::Range(range) => write!(f, "{}..{}", range.start, range.end),
|
|
|
|
ValueData::String(string) => write!(f, "{string}"),
|
|
|
|
ValueData::Struct(r#struct) => write!(f, "{struct}"),
|
2024-03-06 20:36:58 +00:00
|
|
|
}
|
|
|
|
}
|
2024-02-25 19:26:22 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
impl Eq for ValueData {}
|
2024-02-25 19:26:22 +00:00
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
impl PartialOrd for ValueData {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
2024-02-25 19:26:22 +00:00
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
impl Ord for ValueData {
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
|
|
use ValueData::*;
|
|
|
|
|
|
|
|
match (self, other) {
|
|
|
|
(Boolean(left), Boolean(right)) => left.cmp(right),
|
|
|
|
(Boolean(_), _) => Ordering::Greater,
|
|
|
|
(Float(left), Float(right)) => left.total_cmp(right),
|
|
|
|
(Float(_), _) => Ordering::Greater,
|
|
|
|
(Function(left), Function(right)) => left.cmp(right),
|
|
|
|
(Function(_), _) => Ordering::Greater,
|
|
|
|
(Integer(left), Integer(right)) => left.cmp(right),
|
|
|
|
(Integer(_), _) => Ordering::Greater,
|
|
|
|
(List(left), List(right)) => left.cmp(right),
|
|
|
|
(List(_), _) => Ordering::Greater,
|
|
|
|
(Map(left), Map(right)) => left.cmp(right),
|
|
|
|
(Map(_), _) => Ordering::Greater,
|
|
|
|
(Range(left), Range(right)) => {
|
|
|
|
let start_cmp = left.start.cmp(&right.start);
|
|
|
|
|
|
|
|
if start_cmp.is_eq() {
|
|
|
|
left.end.cmp(&right.end)
|
|
|
|
} else {
|
|
|
|
start_cmp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(Range(_), _) => Ordering::Greater,
|
|
|
|
(String(left), String(right)) => left.cmp(right),
|
|
|
|
(String(_), _) => Ordering::Greater,
|
|
|
|
(Struct(left), Struct(right)) => left.cmp(right),
|
|
|
|
(Struct(_), _) => Ordering::Greater,
|
|
|
|
}
|
2024-02-25 19:26:22 +00:00
|
|
|
}
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
impl Serialize for ValueData {
|
2024-06-19 07:32:51 +00:00
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
2024-06-04 18:47:15 +00:00
|
|
|
where
|
2024-08-14 05:03:46 +00:00
|
|
|
S: Serializer,
|
2024-06-19 07:32:51 +00:00
|
|
|
{
|
2024-08-14 05:03:46 +00:00
|
|
|
match self {
|
|
|
|
ValueData::Boolean(boolean) => serializer.serialize_bool(*boolean),
|
|
|
|
ValueData::Float(float) => serializer.serialize_f64(*float),
|
|
|
|
ValueData::Function(function) => function.serialize(serializer),
|
|
|
|
ValueData::Integer(integer) => serializer.serialize_i64(*integer),
|
|
|
|
ValueData::List(list) => {
|
2024-06-19 07:32:51 +00:00
|
|
|
let mut list_ser = serializer.serialize_seq(Some(list.len()))?;
|
|
|
|
|
|
|
|
for item in list {
|
2024-06-19 08:56:56 +00:00
|
|
|
list_ser.serialize_element(&item)?;
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
list_ser.end()
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
ValueData::Map(map) => {
|
2024-06-19 07:32:51 +00:00
|
|
|
let mut map_ser = serializer.serialize_map(Some(map.len()))?;
|
|
|
|
|
|
|
|
for (identifier, value) in map {
|
|
|
|
map_ser.serialize_entry(identifier, value)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
map_ser.end()
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
ValueData::Range(range) => {
|
2024-06-19 07:32:51 +00:00
|
|
|
let mut tuple_ser = serializer.serialize_tuple(2)?;
|
|
|
|
|
|
|
|
tuple_ser.serialize_element(&range.start)?;
|
|
|
|
tuple_ser.serialize_element(&range.end)?;
|
|
|
|
|
|
|
|
tuple_ser.end()
|
|
|
|
}
|
2024-08-14 05:03:46 +00:00
|
|
|
ValueData::String(string) => serializer.serialize_str(string),
|
|
|
|
ValueData::Struct(r#struct) => r#struct.serialize(serializer),
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
struct ValueInnerVisitor;
|
2024-06-19 07:32:51 +00:00
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
impl<'de> Visitor<'de> for ValueInnerVisitor {
|
|
|
|
type Value = ValueData;
|
2024-06-19 07:32:51 +00:00
|
|
|
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
formatter
|
|
|
|
.write_str("a boolean, float, function, integer, list, map, range, string or structure")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
2024-08-14 05:03:46 +00:00
|
|
|
Ok(ValueData::Boolean(v))
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_i64(v as i64)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_i64(v as i64)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_i64(v as i64)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
2024-08-14 05:03:46 +00:00
|
|
|
Ok(ValueData::Integer(v))
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
|
2024-06-19 08:56:56 +00:00
|
|
|
fn visit_i128<E>(self, _: i128) -> Result<Self::Value, E>
|
2024-06-19 07:32:51 +00:00
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_u64(v as u64)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_u64(v as u64)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_u64(v as u64)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
2024-08-14 05:03:46 +00:00
|
|
|
Ok(ValueData::Integer(v as i64))
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
|
2024-06-19 08:56:56 +00:00
|
|
|
fn visit_u128<E>(self, _: u128) -> Result<Self::Value, E>
|
2024-06-19 07:32:51 +00:00
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
2024-06-04 18:47:15 +00:00
|
|
|
{
|
|
|
|
todo!()
|
|
|
|
}
|
2024-06-19 07:32:51 +00:00
|
|
|
|
|
|
|
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_f64(v as f64)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
2024-08-14 05:03:46 +00:00
|
|
|
Ok(ValueData::Float(v))
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_str(v.encode_utf8(&mut [0u8; 4]))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
2024-08-14 05:03:46 +00:00
|
|
|
Ok(ValueData::String(v.to_string()))
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_str(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_str(&v)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
Err(serde::de::Error::invalid_type(
|
|
|
|
serde::de::Unexpected::Bytes(v),
|
|
|
|
&self,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_bytes(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
self.visit_bytes(&v)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_none<E>(self) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
Err(serde::de::Error::invalid_type(
|
|
|
|
serde::de::Unexpected::Option,
|
|
|
|
&self,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
|
|
|
where
|
|
|
|
D: Deserializer<'de>,
|
|
|
|
{
|
|
|
|
let _ = deserializer;
|
|
|
|
Err(serde::de::Error::invalid_type(
|
|
|
|
serde::de::Unexpected::Option,
|
|
|
|
&self,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
|
|
|
where
|
|
|
|
E: serde::de::Error,
|
|
|
|
{
|
|
|
|
Err(serde::de::Error::invalid_type(
|
|
|
|
serde::de::Unexpected::Unit,
|
|
|
|
&self,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
|
|
|
where
|
|
|
|
D: Deserializer<'de>,
|
|
|
|
{
|
|
|
|
let _ = deserializer;
|
|
|
|
Err(serde::de::Error::invalid_type(
|
|
|
|
serde::de::Unexpected::NewtypeStruct,
|
|
|
|
&self,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2024-06-19 08:56:56 +00:00
|
|
|
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
2024-06-19 07:32:51 +00:00
|
|
|
where
|
|
|
|
A: serde::de::SeqAccess<'de>,
|
|
|
|
{
|
2024-06-19 08:56:56 +00:00
|
|
|
let mut list = Vec::with_capacity(seq.size_hint().unwrap_or(10));
|
|
|
|
|
|
|
|
while let Some(element) = seq.next_element()? {
|
|
|
|
list.push(element);
|
|
|
|
}
|
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
Ok(ValueData::List(list))
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
|
2024-06-19 08:56:56 +00:00
|
|
|
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
2024-06-19 07:32:51 +00:00
|
|
|
where
|
|
|
|
A: serde::de::MapAccess<'de>,
|
|
|
|
{
|
2024-08-05 22:45:43 +00:00
|
|
|
let mut btree = BTreeMap::new();
|
2024-06-19 08:56:56 +00:00
|
|
|
|
|
|
|
while let Some((key, value)) = map.next_entry()? {
|
|
|
|
btree.insert(key, value);
|
|
|
|
}
|
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
Ok(ValueData::Map(btree))
|
2024-06-19 07:32:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
|
|
|
where
|
|
|
|
A: serde::de::EnumAccess<'de>,
|
|
|
|
{
|
|
|
|
let _ = data;
|
|
|
|
Err(serde::de::Error::invalid_type(
|
|
|
|
serde::de::Unexpected::Enum,
|
|
|
|
&self,
|
|
|
|
))
|
|
|
|
}
|
2024-06-04 18:47:15 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 05:03:46 +00:00
|
|
|
impl<'de> Deserialize<'de> for ValueData {
|
2024-06-19 07:32:51 +00:00
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
2024-06-04 18:47:15 +00:00
|
|
|
where
|
2024-06-19 07:32:51 +00:00
|
|
|
D: Deserializer<'de>,
|
2024-06-04 18:47:15 +00:00
|
|
|
{
|
2024-08-14 05:03:46 +00:00
|
|
|
deserializer.deserialize_any(ValueInnerVisitor)
|
2024-06-22 17:55:43 +00:00
|
|
|
}
|
2024-03-09 13:10:54 +00:00
|
|
|
}
|
2024-08-05 02:15:31 +00:00
|
|
|
|
2024-08-07 14:03:33 +00:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
|
|
pub struct Function {
|
|
|
|
pub name: Identifier,
|
|
|
|
pub type_parameters: Option<Vec<Type>>,
|
|
|
|
pub value_parameters: Option<Vec<(Identifier, Type)>>,
|
2024-08-13 16:23:25 +00:00
|
|
|
pub return_type: Option<Type>,
|
2024-08-07 23:03:50 +00:00
|
|
|
pub body: AbstractSyntaxTree,
|
2024-08-07 14:03:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Function {
|
2024-08-07 22:24:25 +00:00
|
|
|
pub fn call(
|
2024-08-16 03:17:49 +00:00
|
|
|
&self,
|
2024-08-07 22:46:40 +00:00
|
|
|
_type_arguments: Option<Vec<Type>>,
|
2024-08-07 22:24:25 +00:00
|
|
|
value_arguments: Option<Vec<Value>>,
|
2024-08-12 12:54:21 +00:00
|
|
|
context: &Context,
|
2024-08-07 23:03:50 +00:00
|
|
|
) -> Result<Option<Value>, VmError> {
|
2024-08-12 12:54:21 +00:00
|
|
|
let new_context = Context::with_variables_from(context);
|
2024-08-07 22:24:25 +00:00
|
|
|
|
|
|
|
if let (Some(value_parameters), Some(value_arguments)) =
|
2024-08-16 03:17:49 +00:00
|
|
|
(&self.value_parameters, value_arguments)
|
2024-08-07 22:24:25 +00:00
|
|
|
{
|
|
|
|
for ((identifier, _), value) in value_parameters.into_iter().zip(value_arguments) {
|
2024-08-16 03:17:49 +00:00
|
|
|
new_context.set_value(identifier.clone(), value);
|
2024-08-07 22:24:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-16 03:17:49 +00:00
|
|
|
let mut vm = Vm::new(self.body.clone(), new_context);
|
2024-08-07 22:24:25 +00:00
|
|
|
|
2024-08-12 12:54:21 +00:00
|
|
|
vm.run()
|
2024-08-07 22:24:25 +00:00
|
|
|
}
|
2024-08-07 14:03:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Function {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{}", self.name)?;
|
|
|
|
|
|
|
|
if let Some(type_parameters) = &self.type_parameters {
|
|
|
|
write!(f, "<")?;
|
|
|
|
|
|
|
|
for (index, type_parameter) in type_parameters.iter().enumerate() {
|
|
|
|
if index > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "{}", type_parameter)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ">")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "(")?;
|
|
|
|
|
|
|
|
if let Some(value_paramers) = &self.value_parameters {
|
|
|
|
for (index, (identifier, r#type)) in value_paramers.iter().enumerate() {
|
|
|
|
if index > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "{identifier}: {type}")?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ") {{")?;
|
|
|
|
|
2024-08-14 18:28:39 +00:00
|
|
|
for statement in &self.body.statements {
|
2024-08-07 14:03:33 +00:00
|
|
|
write!(f, "{}", statement)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "}}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-12 19:02:04 +00:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
|
|
pub enum Struct {
|
|
|
|
Unit {
|
|
|
|
name: Identifier,
|
|
|
|
},
|
|
|
|
Tuple {
|
|
|
|
name: Identifier,
|
|
|
|
fields: Vec<Value>,
|
|
|
|
},
|
|
|
|
Fields {
|
|
|
|
name: Identifier,
|
|
|
|
fields: Vec<(Identifier, Value)>,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Struct {
|
|
|
|
pub fn name(&self) -> &Identifier {
|
|
|
|
match self {
|
|
|
|
Struct::Unit { name } => name,
|
|
|
|
Struct::Tuple { name, .. } => name,
|
|
|
|
Struct::Fields { name, .. } => name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Struct {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
Struct::Unit { name } => write!(f, "{}", name),
|
|
|
|
Struct::Tuple { name, fields } => {
|
|
|
|
write!(f, "{}(", name)?;
|
|
|
|
|
|
|
|
for (index, field) in fields.iter().enumerate() {
|
|
|
|
if index > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "{}", field)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ")")
|
|
|
|
}
|
|
|
|
Struct::Fields { name, fields } => {
|
|
|
|
write!(f, "{} {{", name)?;
|
|
|
|
|
|
|
|
for (index, (identifier, r#type)) in fields.iter().enumerate() {
|
|
|
|
if index > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "{}: {}", identifier, r#type)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "}}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-07 14:03:33 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
2024-08-05 02:15:31 +00:00
|
|
|
pub enum ValueError {
|
|
|
|
CannotAdd(Value, Value),
|
2024-08-09 08:56:24 +00:00
|
|
|
CannotAnd(Value, Value),
|
2024-08-09 10:46:24 +00:00
|
|
|
CannotDivide(Value, Value),
|
2024-08-09 07:00:48 +00:00
|
|
|
CannotGreaterThan(Value, Value),
|
|
|
|
CannotGreaterThanOrEqual(Value, Value),
|
2024-08-09 08:56:24 +00:00
|
|
|
CannotLessThan(Value, Value),
|
|
|
|
CannotLessThanOrEqual(Value, Value),
|
2024-08-16 13:22:36 +00:00
|
|
|
CannotMakeMutable,
|
2024-08-09 11:02:55 +00:00
|
|
|
CannotModulo(Value, Value),
|
2024-08-09 08:56:24 +00:00
|
|
|
CannotMultiply(Value, Value),
|
2024-08-14 05:13:43 +00:00
|
|
|
CannotMutate(Value),
|
2024-08-09 08:56:24 +00:00
|
|
|
CannotSubtract(Value, Value),
|
|
|
|
CannotOr(Value, Value),
|
2024-08-09 10:46:24 +00:00
|
|
|
DivisionByZero,
|
2024-08-05 18:58:58 +00:00
|
|
|
ExpectedList(Value),
|
2024-08-09 07:00:48 +00:00
|
|
|
IndexOutOfBounds { value: Value, index: i64 },
|
2024-08-05 02:15:31 +00:00
|
|
|
}
|
2024-08-09 00:58:56 +00:00
|
|
|
|
|
|
|
impl Error for ValueError {}
|
|
|
|
|
|
|
|
impl Display for ValueError {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
ValueError::CannotAdd(left, right) => write!(f, "Cannot add {} and {}", left, right),
|
2024-08-09 08:56:24 +00:00
|
|
|
ValueError::CannotAnd(left, right) => write!(
|
|
|
|
f,
|
|
|
|
"Cannot use logical and operation on {} and {}",
|
|
|
|
left, right
|
|
|
|
),
|
2024-08-09 10:46:24 +00:00
|
|
|
ValueError::CannotDivide(left, right) => {
|
|
|
|
write!(f, "Cannot divide {} by {}", left, right)
|
|
|
|
}
|
2024-08-09 11:02:55 +00:00
|
|
|
ValueError::CannotModulo(left, right) => {
|
|
|
|
write!(f, "Cannot modulo {} by {}", left, right)
|
|
|
|
}
|
2024-08-09 03:28:47 +00:00
|
|
|
ValueError::CannotMultiply(left, right) => {
|
|
|
|
write!(f, "Cannot multiply {} and {}", left, right)
|
|
|
|
}
|
2024-08-16 13:22:36 +00:00
|
|
|
ValueError::CannotMakeMutable => write!(
|
|
|
|
f,
|
|
|
|
"Failed to make mutable value because the value has an immutable reference to it"
|
|
|
|
),
|
2024-08-14 05:13:43 +00:00
|
|
|
ValueError::CannotMutate(value) => write!(f, "Cannot mutate {}", value),
|
2024-08-09 03:28:47 +00:00
|
|
|
ValueError::CannotSubtract(left, right) => {
|
|
|
|
write!(f, "Cannot subtract {} and {}", left, right)
|
|
|
|
}
|
2024-08-09 07:00:48 +00:00
|
|
|
ValueError::CannotLessThan(left, right)
|
|
|
|
| ValueError::CannotLessThanOrEqual(left, right)
|
|
|
|
| ValueError::CannotGreaterThan(left, right)
|
|
|
|
| ValueError::CannotGreaterThanOrEqual(left, right) => {
|
|
|
|
write!(f, "Cannot compare {} and {}", left, right)
|
|
|
|
}
|
2024-08-09 08:56:24 +00:00
|
|
|
ValueError::CannotOr(left, right) => {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"Cannot use logical or operation on {} and {}",
|
|
|
|
left, right
|
|
|
|
)
|
2024-08-09 00:58:56 +00:00
|
|
|
}
|
2024-08-09 10:46:24 +00:00
|
|
|
ValueError::DivisionByZero => write!(f, "Division by zero"),
|
2024-08-09 00:58:56 +00:00
|
|
|
ValueError::IndexOutOfBounds { value, index } => {
|
|
|
|
write!(f, "{} does not have an index of {}", value, index)
|
|
|
|
}
|
|
|
|
ValueError::ExpectedList(value) => write!(f, "{} is not a list", value),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|