From 9c612317dcc1eb90d4c67b34d542f0fe16bccac6 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sat, 12 Oct 2024 04:50:30 -0400 Subject: [PATCH] Refactor values to use register pointers for complex values --- dust-lang/src/chunk.rs | 30 +- dust-lang/src/constructor.rs | 107 --- dust-lang/src/instruction.rs | 2 +- dust-lang/src/lib.rs | 4 +- dust-lang/src/type.rs | 8 +- dust-lang/src/value.rs | 1531 +++++++------------------------- dust-lang/src/vm.rs | 95 +- dust-lang/tests/expressions.rs | 26 +- 8 files changed, 369 insertions(+), 1434 deletions(-) delete mode 100644 dust-lang/src/constructor.rs diff --git a/dust-lang/src/chunk.rs b/dust-lang/src/chunk.rs index c2e8720..09d4158 100644 --- a/dust-lang/src/chunk.rs +++ b/dust-lang/src/chunk.rs @@ -526,7 +526,10 @@ impl<'a> ChunkDisassembler<'a> { for (index, value_option) in self.chunk.constants.iter().enumerate() { let value_display = value_option .as_ref() - .map(|value| value.to_string()) + .map(|value| match value { + Value::Primitive(value_data) => value_data.to_string(), + Value::Object(_) => "object".to_string(), + }) .unwrap_or("empty".to_string()); let trucated_length = 8; let with_elipsis = trucated_length - 3; @@ -540,35 +543,16 @@ impl<'a> ChunkDisassembler<'a> { if let Some(function_disassembly) = value_option.as_ref().and_then(|value| match value { - Value::Raw(value_data) => value_data.as_function().map(|function| { + Value::Primitive(value_data) => value_data.as_function().map(|function| { function - .body() + .body .disassembler("function") .styled(self.styled) .indent(self.indent + 1) .width(self.width) .disassemble() }), - Value::Reference(arc) => arc.as_function().map(|function| { - function - .body() - .disassembler("function") - .styled(self.styled) - .indent(self.indent + 1) - .width(self.width) - .disassemble() - }), - Value::Mutable(rw_lock) => { - rw_lock.read().unwrap().as_function().map(|function| { - function - .body() - .disassembler("function") - .styled(self.styled) - .indent(self.indent + 1) - .width(self.width) - .disassemble() - }) - } + Value::Object(_) => None, }) { push(&function_disassembly, false); diff --git a/dust-lang/src/constructor.rs b/dust-lang/src/constructor.rs deleted file mode 100644 index ee847b5..0000000 --- a/dust-lang/src/constructor.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::{ - collections::HashMap, - fmt::{self, Display, Formatter}, -}; - -use serde::{Deserialize, Serialize}; - -use crate::{Identifier, Struct, StructType, TypeConflict, Value}; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -pub struct Constructor { - pub struct_type: StructType, -} - -impl Constructor { - pub fn construct_unit(&self) -> Result { - if let StructType::Unit { name } = &self.struct_type { - Ok(Value::r#struct(Struct::Unit { name: name.clone() })) - } else { - Err(ConstructError::ExpectedUnit) - } - } - - pub fn construct_tuple(&self, fields: Vec) -> Result { - if let StructType::Tuple { - name: expected_name, - fields: expected_fields, - } = &self.struct_type - { - if fields.len() != expected_fields.len() { - return Err(ConstructError::FieldCountMismatch); - } - - for (i, value) in fields.iter().enumerate() { - let expected_type = expected_fields.get(i).unwrap(); - let actual_type = value.r#type(); - - expected_type.check(&actual_type)?; - } - - Ok(Value::r#struct(Struct::Tuple { - name: expected_name.clone(), - fields, - })) - } else { - Err(ConstructError::ExpectedTuple) - } - } - - pub fn construct_fields( - &self, - fields: HashMap, - ) -> Result { - if let StructType::Fields { - name: expected_name, - fields: expected_fields, - } = &self.struct_type - { - if fields.len() != expected_fields.len() { - return Err(ConstructError::FieldCountMismatch); - } - - for (field_name, field_value) in fields.iter() { - let expected_type = expected_fields.get(field_name).unwrap(); - let actual_type = field_value.r#type(); - - expected_type.check(&actual_type)?; - } - - Ok(Value::r#struct(Struct::Fields { - name: expected_name.clone(), - fields, - })) - } else { - Err(ConstructError::ExpectedFields) - } - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -pub enum ConstructError { - FieldCountMismatch, - ExpectedUnit, - ExpectedTuple, - ExpectedFields, - TypeConflict(TypeConflict), -} - -impl From for ConstructError { - fn from(conflict: TypeConflict) -> Self { - Self::TypeConflict(conflict) - } -} - -impl Display for ConstructError { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - ConstructError::FieldCountMismatch => write!(f, "Field count mismatch"), - ConstructError::ExpectedUnit => write!(f, "Expected unit struct"), - ConstructError::ExpectedTuple => write!(f, "Expected tuple struct"), - ConstructError::ExpectedFields => write!(f, "Expected fields struct"), - ConstructError::TypeConflict(TypeConflict { expected, actual }) => { - write!(f, "Type conflict: expected {}, got {}", expected, actual) - } - } - } -} diff --git a/dust-lang/src/instruction.rs b/dust-lang/src/instruction.rs index f56cafe..3d6bb2a 100644 --- a/dust-lang/src/instruction.rs +++ b/dust-lang/src/instruction.rs @@ -394,7 +394,7 @@ impl Instruction { let constant = if let Some(chunk) = chunk { match chunk.get_constant(constant_index, Span(0, 0)) { - Ok(constant) => constant.to_string(), + Ok(value) => value.to_string(), Err(error) => format!("{error:?}"), } } else { diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 9edcebb..56f350b 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -1,5 +1,4 @@ mod chunk; -mod constructor; mod dust_error; mod identifier; mod instruction; @@ -14,7 +13,6 @@ mod vm; use std::fmt::Display; pub use chunk::{Chunk, ChunkDisassembler, ChunkError, Local}; -pub use constructor::Constructor; pub use dust_error::{AnnotatedError, DustError}; pub use identifier::Identifier; pub use instruction::Instruction; @@ -23,7 +21,7 @@ pub use operation::Operation; pub use parser::{parse, ParseError, Parser}; pub use r#type::{EnumType, FunctionType, RangeableType, StructType, Type, TypeConflict}; pub use token::{Token, TokenKind, TokenOwned}; -pub use value::{Enum, Function, Struct, Value, ValueError}; +pub use value::{Function, Value, ValueError}; pub use vm::{run, Vm, VmError}; use serde::{Deserialize, Serialize}; diff --git a/dust-lang/src/type.rs b/dust-lang/src/type.rs index 4e97b06..2e1a15f 100644 --- a/dust-lang/src/type.rs +++ b/dust-lang/src/type.rs @@ -17,7 +17,7 @@ use std::{ use serde::{Deserialize, Serialize}; -use crate::{Constructor, Identifier}; +use crate::Identifier; /// Description of a kind of value. /// @@ -488,12 +488,6 @@ impl StructType { StructType::Fields { name, .. } => name, } } - - pub fn constructor(&self) -> Constructor { - Constructor { - struct_type: self.clone(), - } - } } impl Display for StructType { diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index 5108982..c348f36 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -12,17 +12,6 @@ //! 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 `r#type` method: //! //! ``` @@ -33,662 +22,159 @@ //! ``` use std::{ cmp::Ordering, - collections::HashMap, fmt::{self, Debug, Display, Formatter}, ops::{Range, RangeInclusive}, - sync::{Arc, RwLock}, }; use serde::{ - de::{self, MapAccess, SeqAccess, Visitor}, - ser::SerializeMap, + de::{self, Visitor}, Deserialize, Deserializer, Serialize, Serializer, }; -use crate::{Chunk, EnumType, Identifier, RangeableType, StructType, Type}; +use crate::{Chunk, RangeableType, Span, Type, Vm, VmError}; /// Dust value representation /// /// See the [module-level documentation][self] for more. +#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Value { - Raw(ValueData), - Reference(Arc), - Mutable(Arc>), + Primitive(Primitive), + Object(Object), } impl Value { pub fn boolean(value: bool) -> Self { - Value::Raw(ValueData::Boolean(value)) + Value::Primitive(Primitive::Boolean(value)) } pub fn byte(value: u8) -> Self { - Value::Raw(ValueData::Byte(value)) + Value::Primitive(Primitive::Byte(value)) } pub fn character(value: char) -> Self { - Value::Raw(ValueData::Character(value)) + Value::Primitive(Primitive::Character(value)) } pub fn float(value: f64) -> Self { - Value::Raw(ValueData::Float(value)) + Value::Primitive(Primitive::Float(value)) } pub fn function(body: Chunk) -> Self { - Value::Raw(ValueData::Function(Function { body })) + Value::Primitive(Primitive::Function(Function { body })) } pub fn integer>(into_i64: T) -> Self { - Value::Raw(ValueData::Integer(into_i64.into())) + Value::Primitive(Primitive::Integer(into_i64.into())) + } + + pub fn list(start: u8, end: u8) -> Self { + Value::Object(Object::List { start, end }) } pub fn string(to_string: T) -> Self { - Value::Raw(ValueData::String(to_string.to_string())) - } - - pub fn list>>(values: T) -> Self { - Value::Raw(ValueData::List(values.into())) - } - - pub fn map>>(into_map: T) -> Self { - Value::Raw(ValueData::Map(into_map.into())) - } - - pub fn mutable(value: Value) -> Self { - match value { - Value::Raw(data) => Value::Mutable(Arc::new(RwLock::new(data))), - Value::Reference(data) => Value::Mutable(Arc::new(RwLock::new(data.as_ref().clone()))), - Value::Mutable(_) => value, - } - } - - pub fn range>(range: T) -> Self { - Value::Raw(ValueData::Range(range.into())) - } - - pub fn r#struct(value: Struct) -> Self { - Value::Raw(ValueData::Struct(value)) - } - - pub fn reference(value: Value) -> Self { - match value { - Value::Raw(data) => Value::Reference(Arc::new(data)), - Value::Reference(_) => value, - Value::Mutable(data) => { - let data = data.read().unwrap(); - - Value::Reference(Arc::new(data.clone())) - } - } - } - - pub fn into_raw(self) -> Self { - match self { - Value::Raw(_) => self, - Value::Reference(data) => Value::Raw(data.as_ref().clone()), - Value::Mutable(data) => Value::Raw(data.read().unwrap().clone()), - } - } - - pub fn into_reference(self) -> Self { - log::trace!("Converting to reference: {self:?}"); - - match self { - Value::Raw(data) => Value::Reference(Arc::new(data)), - Value::Reference(_) => self, - Value::Mutable(data) => { - let data = data.read().unwrap(); - - Value::Reference(Arc::new(data.clone())) - } - } - } - - pub fn into_mutable(self) -> Self { - match self { - Value::Raw(data) => { - log::trace!("Converting to mutable: {data:?}"); - - Value::Mutable(Arc::new(RwLock::new(data))) - } - Value::Reference(data) => { - log::trace!("Converting to mutable: {data:?}"); - - Value::Mutable(Arc::new(RwLock::new(data.as_ref().clone()))) - } - Value::Mutable(_) => self, - } - } - - pub fn clone_data(&self) -> ValueData { - match self { - Value::Raw(data) => data.clone(), - Value::Reference(data) => data.as_ref().clone(), - Value::Mutable(data) => data.read().unwrap().clone(), - } - } - - pub fn is_rangeable(&self) -> bool { - match self { - Value::Raw(data) => data.is_rangeable(), - Value::Reference(data) => data.is_rangeable(), - Value::Mutable(data) => data.read().unwrap().is_rangeable(), - } - } - - pub fn is_raw(&self) -> bool { - matches!(self, Value::Raw(_)) - } - - pub fn is_reference(&self) -> bool { - matches!(self, Value::Reference(_)) - } - - pub fn is_mutable(&self) -> bool { - matches!(self, Value::Mutable(_)) - } - - pub fn as_mutable(&self) -> Option<&Arc>> { - match self { - Value::Mutable(data) => Some(data), - _ => None, - } - } - - pub fn as_boolean(&self) -> Option { - match self { - Value::Raw(ValueData::Boolean(value)) => Some(*value), - Value::Reference(data) => match data.as_ref() { - ValueData::Boolean(value) => Some(*value), - _ => None, - }, - Value::Mutable(data) => match *data.read().unwrap() { - ValueData::Boolean(value) => Some(value), - _ => None, - }, - _ => None, - } - } - - pub fn as_byte(&self) -> Option { - match self { - Value::Raw(ValueData::Byte(value)) => Some(*value), - Value::Reference(data) => match data.as_ref() { - ValueData::Byte(value) => Some(*value), - _ => None, - }, - Value::Mutable(data) => match *data.read().unwrap() { - ValueData::Byte(value) => Some(value), - _ => None, - }, - _ => None, - } - } - - pub fn as_character(&self) -> Option { - match self { - Value::Raw(ValueData::Character(value)) => Some(*value), - Value::Reference(data) => match data.as_ref() { - ValueData::Character(value) => Some(*value), - _ => None, - }, - Value::Mutable(data) => match *data.read().unwrap() { - ValueData::Character(value) => Some(value), - _ => None, - }, - _ => None, - } - } - - pub fn as_float(&self) -> Option { - match self { - Value::Raw(ValueData::Float(value)) => Some(*value), - Value::Reference(data) => match data.as_ref() { - ValueData::Float(value) => Some(*value), - _ => None, - }, - Value::Mutable(data) => match *data.read().unwrap() { - ValueData::Float(value) => Some(value), - _ => None, - }, - _ => None, - } - } - - pub fn as_integer(&self) -> Option { - match self { - Value::Raw(ValueData::Integer(value)) => Some(*value), - Value::Reference(data) => match data.as_ref() { - ValueData::Integer(value) => Some(*value), - _ => None, - }, - Value::Mutable(data) => match *data.read().unwrap() { - ValueData::Integer(value) => Some(value), - _ => None, - }, - _ => None, - } + Value::Primitive(Primitive::String(to_string.to_string())) } pub fn r#type(&self) -> Type { match self { - Value::Raw(data) => data.r#type(), - Value::Reference(data) => data.r#type(), - Value::Mutable(data) => data.read().unwrap().r#type(), - } - } - - pub fn mutate(&self, value: Value) -> Result<(), ValueError> { - match self { - Value::Mutable(data) => { - let mut data = data.write().unwrap(); - *data = value.clone_data(); - - Ok(()) - } - _ => Err(ValueError::CannotMutate(self.clone())), - } - } - - pub fn index(&self, index_value: &Value) -> Result { - let collection = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let index = match index_value { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - - match (collection, index) { - (ValueData::List(values), ValueData::Integer(index)) => values - .get(*index as usize) - .cloned() - .ok_or_else(|| ValueError::IndexOutOfBounds { - value: self.clone(), - index: *index, - }), - (ValueData::List(values), ValueData::Range(RangeValue::IntegerRange(range))) => { - if range.start < 0 || range.start > values.len() as i64 { - return Err(ValueError::IndexOutOfBounds { - value: self.clone(), - index: range.start, - }); - } - - if range.end < 0 || range.end > values.len() as i64 { - return Err(ValueError::IndexOutOfBounds { - value: self.clone(), - index: range.end, - }); - } - - let slice = values - .get(range.start as usize..range.end as usize) - .unwrap(); - - Ok(Value::list(slice.to_vec())) - } - (ValueData::String(string), ValueData::Integer(index)) => { - let index = *index as usize; - let character = - string - .chars() - .nth(index) - .ok_or_else(|| ValueError::IndexOutOfBounds { - value: self.clone(), - index: index as i64, - })?; - - Ok(Value::character(character)) - } - _ => Err(ValueError::CannotIndex { - value: self.clone(), - index: index_value.clone(), - }), - } - } - - pub fn get_field(&self, field: &Identifier) -> Option { - let data = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - - match field.as_str() { - "is_even" => match data { - ValueData::Integer(integer) => Some(Value::boolean(integer % 2 == 0)), - ValueData::Float(float) => Some(Value::boolean(float % 2.0 == 0.0)), - _ => None, - }, - "is_odd" => match data { - ValueData::Integer(integer) => Some(Value::boolean(integer % 2 != 0)), - ValueData::Float(float) => Some(Value::boolean(float % 2.0 != 0.0)), - _ => None, - }, - "length" => match data { - ValueData::List(values) => Some(Value::integer(values.len() as i64)), - ValueData::String(string) => Some(Value::integer(string.len() as i64)), - ValueData::Map(map) => Some(Value::integer(map.len() as i64)), - _ => None, - }, - _ => match data { - ValueData::Struct(Struct::Fields { fields, .. }) => fields.get(field).cloned(), - ValueData::Map(pairs) => pairs.get(field).cloned(), - _ => None, - }, + Value::Primitive(data) => data.r#type(), + Value::Object(object) => todo!(), } } pub fn add(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; let sum = left .add(right) .ok_or_else(|| ValueError::CannotAdd(self.clone(), other.clone()))?; - Ok(Value::Raw(sum)) - } - - pub fn add_assign(&self, other: &Value) -> Result<(), ValueError> { - let mut left = self - .as_mutable() - .ok_or(ValueError::CannotMutate(self.clone()))? - .write() - .unwrap(); - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let new_data = left - .add(right) - .ok_or_else(|| ValueError::CannotAdd(self.clone(), other.clone()))?; - - *left = new_data; - - Ok(()) + Ok(Value::Primitive(sum)) } pub fn subtract(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; let difference = left .subtract(right) .ok_or_else(|| ValueError::CannotSubtract(self.clone(), other.clone()))?; - Ok(Value::Raw(difference)) - } - - pub fn subtract_assign(&self, other: &Value) -> Result<(), ValueError> { - let mut left = self - .as_mutable() - .ok_or(ValueError::CannotMutate(self.clone()))? - .write() - .unwrap(); - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let new_data = left - .subtract(right) - .ok_or_else(|| ValueError::CannotSubtract(self.clone(), other.clone()))?; - - *left = new_data; - - Ok(()) + Ok(Value::Primitive(difference)) } pub fn multiply(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; let product = left .multiply(right) .ok_or_else(|| ValueError::CannotMultiply(self.clone(), other.clone()))?; - Ok(Value::Raw(product)) - } - - pub fn multiply_assign(&self, other: &Value) -> Result<(), ValueError> { - let mut left = self - .as_mutable() - .ok_or(ValueError::CannotMutate(self.clone()))? - .write() - .unwrap(); - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let new_data = left - .multiply(right) - .ok_or_else(|| ValueError::CannotMultiply(self.clone(), other.clone()))?; - - *left = new_data; - - Ok(()) + Ok(Value::Primitive(product)) } pub fn divide(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; let quotient = left .divide(right) .ok_or_else(|| ValueError::CannotDivide(self.clone(), other.clone()))?; - Ok(Value::Raw(quotient)) - } - - pub fn divide_assign(&self, other: &Value) -> Result<(), ValueError> { - let mut left = self - .as_mutable() - .ok_or(ValueError::CannotMutate(self.clone()))? - .write() - .unwrap(); - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let new_data = left - .divide(right) - .ok_or_else(|| ValueError::CannotDivide(self.clone(), other.clone()))?; - - *left = new_data; - - Ok(()) + Ok(Value::Primitive(quotient)) } pub fn modulo(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; let remainder = left .modulo(right) .ok_or_else(|| ValueError::CannotModulo(self.clone(), other.clone()))?; - Ok(Value::Raw(remainder)) - } - - pub fn modulo_assign(&self, other: &Value) -> Result<(), ValueError> { - let mut left = self - .as_mutable() - .ok_or(ValueError::CannotMutate(self.clone()))? - .write() - .unwrap(); - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let new_data = left - .modulo(right) - .ok_or_else(|| ValueError::CannotModulo(self.clone(), other.clone()))?; - - *left = new_data; - - Ok(()) - } - - pub fn is_even(&self) -> Result { - let data = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - - data.is_even() - .ok_or_else(|| ValueError::CannotModulo(self.clone(), Value::integer(2))) - .map(Value::Raw) - } - - pub fn is_odd(&self) -> Result { - let data = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - - data.is_odd() - .ok_or_else(|| ValueError::CannotModulo(self.clone(), Value::integer(2))) - .map(Value::Raw) - } - - pub fn greater_than(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - - left.greater_than(right) - .ok_or_else(|| ValueError::CannotGreaterThan(self.clone(), other.clone())) - .map(Value::Raw) - } - - pub fn greater_than_or_equal(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - - left.greater_than_or_equal(right) - .ok_or_else(|| ValueError::CannotGreaterThanOrEqual(self.clone(), other.clone())) - .map(Value::Raw) + Ok(Value::Primitive(remainder)) } pub fn less_than(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; - left.less_than(right) - .ok_or_else(|| ValueError::CannotLessThan(self.clone(), other.clone())) - .map(Value::Raw) + Ok(Value::boolean(left < right)) } pub fn less_than_or_equal(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; left.less_than_or_equal(right) .ok_or_else(|| ValueError::CannotLessThanOrEqual(self.clone(), other.clone())) - .map(Value::Raw) + .map(Value::Primitive) } pub fn equal(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; Ok(Value::boolean(left == right)) } pub fn not_equal(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; Ok(Value::boolean(left != right)) @@ -696,77 +182,41 @@ impl Value { pub fn negate(&self) -> Result { let data = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + Value::Primitive(data) => data, + _ => return Err(ValueError::CannotNot(self.clone())), }; data.negate() - .ok_or_else(|| ValueError::CannotNegate(self.clone())) - .map(Value::Raw) + .ok_or_else(|| ValueError::CannotNot(self.clone())) + .map(Value::Primitive) } pub fn not(&self) -> Result { let data = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + Value::Primitive(data) => data, + _ => return Err(ValueError::CannotNot(self.clone())), }; data.not() .ok_or_else(|| ValueError::CannotNot(self.clone())) - .map(Value::Raw) + .map(Value::Primitive) } pub fn and(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), + let (left, right) = match (self, other) { + (Value::Primitive(left), Value::Primitive(right)) => (left, right), + _ => return Err(ValueError::CannotAdd(self.clone(), other.clone())), }; left.and(right) .ok_or_else(|| ValueError::CannotAnd(self.clone(), other.clone())) - .map(Value::Raw) + .map(Value::Primitive) } - pub fn or(&self, other: &Value) -> Result { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - - left.or(right) - .ok_or_else(|| ValueError::CannotOr(self.clone(), other.clone())) - .map(Value::Raw) - } - - pub fn kind(&self) -> ValueKind { + pub fn display(&self, vm: &Vm, position: Span) -> Result { match self { - Value::Raw(_) => ValueKind::Raw, - Value::Reference(_) => ValueKind::Reference, - Value::Mutable(_) => ValueKind::Mutable, - } - } -} - -impl Display for Value { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - Value::Raw(data) => write!(f, "{}", data), - Value::Reference(data) => write!(f, "{}", data), - Value::Mutable(data) => write!(f, "{}", data.read().unwrap()), + Value::Primitive(primitive) => Ok(primitive.to_string()), + Value::Object(object) => object.display(vm, position), } } } @@ -824,63 +274,17 @@ impl Clone for Value { log::trace!("Cloning value {:?}", self); match self { - Value::Raw(data) => Value::Raw(data.clone()), - Value::Reference(data) => Value::Reference(data.clone()), - Value::Mutable(data) => Value::Mutable(data.clone()), + Value::Primitive(data) => Value::Primitive(data.clone()), + Value::Object(object) => Value::Object(object.clone()), } } } -impl Debug for Value { +impl Display for Value { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Value::Raw(data) => write!(f, "Value::Raw({data:?})"), - Value::Reference(data) => write!(f, "Value::Reference({data:?})"), - Value::Mutable(data) => { - let data = data.read().unwrap(); - - write!(f, "Value::Mutable({data:?})") - } - } - } -} - -impl Eq for Value {} - -impl PartialEq for Value { - fn eq(&self, other: &Self) -> bool { - let left = match self { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - let right = match other { - Value::Raw(data) => data, - Value::Reference(data) => data, - Value::Mutable(data) => &data.read().unwrap(), - }; - - left == right - } -} - -impl PartialOrd for Value { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Value { - fn cmp(&self, other: &Self) -> Ordering { - match (self, other) { - (Value::Raw(left), Value::Raw(right)) => left.cmp(right), - (Value::Raw(_), _) => Ordering::Greater, - (Value::Reference(left), Value::Reference(right)) => left.cmp(right), - (Value::Reference(_), _) => Ordering::Greater, - (Value::Mutable(left), Value::Mutable(right)) => { - left.read().unwrap().cmp(&right.read().unwrap()) - } - (Value::Mutable(_), _) => Ordering::Greater, + Value::Primitive(primitive) => write!(f, "{primitive}"), + Value::Object(_) => write!(f, "object"), } } } @@ -888,9 +292,8 @@ impl Ord for Value { impl Serialize for Value { fn serialize(&self, serializer: S) -> Result { match self { - Value::Raw(data) => data.serialize(serializer), - Value::Reference(data) => data.serialize(serializer), - Value::Mutable(data) => data.read().unwrap().serialize(serializer), + Value::Primitive(data) => data.serialize(serializer), + Value::Object(object) => object.serialize(serializer), } } } @@ -907,59 +310,27 @@ impl<'de> Deserialize<'de> for Value { } fn visit_bool(self, value: bool) -> Result { - Ok(Value::Raw(ValueData::Boolean(value))) + Ok(Value::Primitive(Primitive::Boolean(value))) } fn visit_i64(self, value: i64) -> Result { - Ok(Value::Raw(ValueData::Integer(value))) + Ok(Value::Primitive(Primitive::Integer(value))) } fn visit_u64(self, value: u64) -> Result { - Ok(Value::Raw(ValueData::Integer(value as i64))) + Ok(Value::Primitive(Primitive::Integer(value as i64))) } fn visit_f64(self, value: f64) -> Result { - Ok(Value::Raw(ValueData::Float(value))) + Ok(Value::Primitive(Primitive::Float(value))) } fn visit_str(self, value: &str) -> Result { - Ok(Value::Raw(ValueData::String(value.to_string()))) + Ok(Value::Primitive(Primitive::String(value.to_string()))) } fn visit_string(self, value: String) -> Result { - Ok(Value::Raw(ValueData::String(value))) - } - - fn visit_seq>(self, mut seq: A) -> Result { - let mut values = Vec::new(); - - while let Some(value) = seq.next_element()? { - values.push(value); - } - - Ok(Value::Raw(ValueData::List(values))) - } - - fn visit_map>(self, mut map: A) -> Result { - let mut values = HashMap::new(); - - while let Some((key, value)) = map.next_entry()? { - values.insert(key, value); - } - - Ok(Value::Raw(ValueData::Map(values))) - } - - fn visit_bytes(self, value: &[u8]) -> Result { - Ok(Value::Raw(ValueData::List( - value.iter().map(|&byte| Value::byte(byte)).collect(), - ))) - } - - fn visit_byte_buf(self, value: Vec) -> Result { - Ok(Value::Raw(ValueData::List( - value.iter().map(|&byte| Value::byte(byte)).collect(), - ))) + Ok(Value::Primitive(Primitive::String(value))) } } @@ -967,104 +338,36 @@ impl<'de> Deserialize<'de> for Value { } } -#[derive(Clone, Debug)] -pub enum ValueKind { - Raw, - Reference, - Mutable, -} - -impl Display for ValueKind { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - ValueKind::Raw => write!(f, "raw"), - ValueKind::Reference => write!(f, "reference"), - ValueKind::Mutable => write!(f, "mutable"), - } - } -} - -#[derive(Clone, Debug)] -pub enum ValueData { +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub enum Primitive { Boolean(bool), Byte(u8), Character(char), - Enum(Enum), Float(f64), Function(Function), Integer(i64), - List(Vec), - Map(HashMap), Range(RangeValue), String(String), - Struct(Struct), - Tuple(Vec), } -impl ValueData { +impl Primitive { pub fn r#type(&self) -> Type { match self { - ValueData::Boolean(_) => Type::Boolean, - ValueData::Byte(_) => Type::Byte, - ValueData::Character(_) => Type::Character, - ValueData::Function(Function { .. }) => todo!(), - ValueData::Enum(Enum { r#type, .. }) => Type::Enum(r#type.clone()), - ValueData::Float(_) => Type::Float, - 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(map) => { - let pairs = map - .iter() - .map(|(key, value)| (key.clone(), value.r#type())) - .collect(); - - Type::Map { pairs } - } - ValueData::Range(range) => range.r#type(), - ValueData::String(string) => Type::String { + Primitive::Boolean(_) => Type::Boolean, + Primitive::Byte(_) => Type::Byte, + Primitive::Character(_) => Type::Character, + Primitive::Function(Function { .. }) => todo!(), + Primitive::Float(_) => Type::Float, + Primitive::Integer(_) => Type::Integer, + Primitive::Range(range) => range.r#type(), + Primitive::String(string) => Type::String { length: Some(string.len()), }, - ValueData::Struct(r#struct) => match r#struct { - Struct::Unit { name } => Type::Struct(StructType::Unit { name: name.clone() }), - Struct::Tuple { name, fields } => { - let types = fields.iter().map(|field| field.r#type()).collect(); - - Type::Struct(StructType::Tuple { - name: name.clone(), - fields: types, - }) - } - Struct::Fields { name, fields } => { - let types = fields - .iter() - .map(|(identifier, value)| (identifier.clone(), value.r#type())) - .collect(); - - Type::Struct(StructType::Fields { - name: name.clone(), - fields: types, - }) - } - }, - ValueData::Tuple(values) => { - let fields = values.iter().map(|value| value.r#type()).collect(); - - Type::Tuple { - fields: Some(fields), - } - } } } pub fn as_function(&self) -> Option<&Function> { - if let ValueData::Function(function) = self { + if let Primitive::Function(function) = self { Some(function) } else { None @@ -1074,195 +377,194 @@ impl ValueData { pub fn is_rangeable(&self) -> bool { matches!( self, - ValueData::Integer(_) - | ValueData::Float(_) - | ValueData::Character(_) - | ValueData::Byte(_) + Primitive::Integer(_) + | Primitive::Float(_) + | Primitive::Character(_) + | Primitive::Byte(_) ) } - pub fn add(&self, other: &ValueData) -> Option { + pub fn add(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Byte(left), ValueData::Byte(right)) => { - Some(ValueData::Byte(left.saturating_add(*right))) + (Primitive::Byte(left), Primitive::Byte(right)) => { + Some(Primitive::Byte(left.saturating_add(*right))) } - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Float(left + right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Float(left + right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Integer(left.saturating_add(*right))) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Integer(left.saturating_add(*right))) } - (ValueData::String(left), ValueData::String(right)) => { - Some(ValueData::String(format!("{}{}", left, right))) + (Primitive::String(left), Primitive::String(right)) => { + Some(Primitive::String(format!("{}{}", left, right))) } _ => None, } } - pub fn subtract(&self, other: &ValueData) -> Option { + pub fn subtract(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Byte(left), ValueData::Byte(right)) => { - Some(ValueData::Byte(left.saturating_sub(*right))) + (Primitive::Byte(left), Primitive::Byte(right)) => { + Some(Primitive::Byte(left.saturating_sub(*right))) } - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Float(left - right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Float(left - right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Integer(left.saturating_sub(*right))) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Integer(left.saturating_sub(*right))) } _ => None, } } - pub fn multiply(&self, other: &ValueData) -> Option { + pub fn multiply(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Byte(left), ValueData::Byte(right)) => { - Some(ValueData::Byte(left.saturating_mul(*right))) + (Primitive::Byte(left), Primitive::Byte(right)) => { + Some(Primitive::Byte(left.saturating_mul(*right))) } - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Float(left * right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Float(left * right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Integer(left.saturating_mul(*right))) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Integer(left.saturating_mul(*right))) } _ => None, } } - pub fn divide(&self, other: &ValueData) -> Option { + pub fn divide(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Byte(left), ValueData::Byte(right)) => { - Some(ValueData::Byte(left.saturating_div(*right))) + (Primitive::Byte(left), Primitive::Byte(right)) => { + Some(Primitive::Byte(left.saturating_div(*right))) } - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Float(left / right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Float(left / right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Integer(left.saturating_div(*right))) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Integer(left.saturating_div(*right))) } _ => None, } } - pub fn modulo(&self, other: &ValueData) -> Option { + pub fn modulo(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Float(left % right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Float(left % right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Integer(left % right)) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Integer(left % right)) } _ => None, } } - pub fn less_than(&self, other: &ValueData) -> Option { + pub fn less_than(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Boolean(left < right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Boolean(left < right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Boolean(left < right)) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Boolean(left < right)) } _ => None, } } - pub fn less_than_or_equal(&self, other: &ValueData) -> Option { + pub fn less_than_or_equal(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Boolean(left <= right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Boolean(left <= right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Boolean(left <= right)) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Boolean(left <= right)) } _ => None, } } - pub fn greater_than(&self, other: &ValueData) -> Option { + pub fn greater_than(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Boolean(left > right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Boolean(left > right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Boolean(left > right)) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Boolean(left > right)) } _ => None, } } - pub fn greater_than_or_equal(&self, other: &ValueData) -> Option { + pub fn greater_than_or_equal(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Float(left), ValueData::Float(right)) => { - Some(ValueData::Boolean(left >= right)) + (Primitive::Float(left), Primitive::Float(right)) => { + Some(Primitive::Boolean(left >= right)) } - (ValueData::Integer(left), ValueData::Integer(right)) => { - Some(ValueData::Boolean(left >= right)) + (Primitive::Integer(left), Primitive::Integer(right)) => { + Some(Primitive::Boolean(left >= right)) } _ => None, } } - pub fn and(&self, other: &ValueData) -> Option { + pub fn and(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Boolean(left), ValueData::Boolean(right)) => { - Some(ValueData::Boolean(*left && *right)) + (Primitive::Boolean(left), Primitive::Boolean(right)) => { + Some(Primitive::Boolean(*left && *right)) } _ => None, } } - pub fn or(&self, other: &ValueData) -> Option { + pub fn or(&self, other: &Primitive) -> Option { match (self, other) { - (ValueData::Boolean(left), ValueData::Boolean(right)) => { - Some(ValueData::Boolean(*left || *right)) + (Primitive::Boolean(left), Primitive::Boolean(right)) => { + Some(Primitive::Boolean(*left || *right)) } _ => None, } } - pub fn is_even(&self) -> Option { + pub fn is_even(&self) -> Option { match self { - ValueData::Integer(integer) => Some(ValueData::Boolean(integer % 2 == 0)), - ValueData::Float(float) => Some(ValueData::Boolean(float % 2.0 == 0.0)), + Primitive::Integer(integer) => Some(Primitive::Boolean(integer % 2 == 0)), + Primitive::Float(float) => Some(Primitive::Boolean(float % 2.0 == 0.0)), _ => None, } } - pub fn is_odd(&self) -> Option { + pub fn is_odd(&self) -> Option { match self { - ValueData::Integer(integer) => Some(ValueData::Boolean(integer % 2 != 0)), - ValueData::Float(float) => Some(ValueData::Boolean(float % 2.0 != 0.0)), + Primitive::Integer(integer) => Some(Primitive::Boolean(integer % 2 != 0)), + Primitive::Float(float) => Some(Primitive::Boolean(float % 2.0 != 0.0)), _ => None, } } - pub fn negate(&self) -> Option { + pub fn negate(&self) -> Option { match self { - ValueData::Byte(value) => Some(ValueData::Byte(!value)), - ValueData::Float(value) => Some(ValueData::Float(-value)), - ValueData::Integer(value) => Some(ValueData::Integer(-value)), + Primitive::Byte(value) => Some(Primitive::Byte(!value)), + Primitive::Float(value) => Some(Primitive::Float(-value)), + Primitive::Integer(value) => Some(Primitive::Integer(-value)), _ => None, } } - pub fn not(&self) -> Option { + pub fn not(&self) -> Option { match self { - ValueData::Boolean(value) => Some(ValueData::Boolean(!value)), + Primitive::Boolean(value) => Some(Primitive::Boolean(!value)), _ => None, } } } -impl Display for ValueData { +impl Display for Primitive { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - ValueData::Boolean(boolean) => write!(f, "{boolean}"), - ValueData::Byte(byte) => write!(f, "0x{byte:02x}"), - ValueData::Character(character) => write!(f, "{character}"), - ValueData::Enum(r#enum) => write!(f, "{enum}"), - ValueData::Float(float) => { + Primitive::Boolean(boolean) => write!(f, "{boolean}"), + Primitive::Byte(byte) => write!(f, "0x{byte:02x}"), + Primitive::Character(character) => write!(f, "{character}"), + Primitive::Float(float) => { write!(f, "{float}")?; if float.fract() == 0.0 { @@ -1271,308 +573,62 @@ impl Display for ValueData { Ok(()) } - ValueData::Function(Function { .. }) => { + Primitive::Function(Function { .. }) => { write!(f, "function") } - ValueData::Integer(integer) => write!(f, "{integer}"), - ValueData::Map(pairs) => { - write!(f, "{{ ")?; - - for (index, (key, value)) in pairs.iter().enumerate() { - write!(f, "{key}: {value}")?; - - if index < pairs.len() - 1 { - write!(f, ", ")?; - } - } - - write!(f, " }}") - } - ValueData::List(list) => { - write!(f, "[")?; - - for (index, value) in list.iter().enumerate() { - write!(f, "{}", value)?; - - if index < list.len() - 1 { - write!(f, ", ")?; - } - } - - write!(f, "]") - } - ValueData::Range(range_value) => { + Primitive::Integer(integer) => write!(f, "{integer}"), + Primitive::Range(range_value) => { write!(f, "{range_value}") } - ValueData::String(string) => write!(f, "{string}"), - ValueData::Struct(r#struct) => write!(f, "{struct}"), - ValueData::Tuple(fields) => { - write!(f, "(")?; - - for (index, field) in fields.iter().enumerate() { - write!(f, "{}", field)?; - - if index < fields.len() - 1 { - write!(f, ", ")?; - } - } - - write!(f, ")") - } + Primitive::String(string) => write!(f, "{string}"), } } } -impl Eq for ValueData {} +impl Eq for Primitive {} -impl PartialEq for ValueData { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (ValueData::Boolean(left), ValueData::Boolean(right)) => left == right, - (ValueData::Byte(left), ValueData::Byte(right)) => left == right, - (ValueData::Character(left), ValueData::Character(right)) => left == right, - (ValueData::Float(left), ValueData::Float(right)) => left == right, - (ValueData::Function(left), ValueData::Function(right)) => left == right, - (ValueData::Integer(left), ValueData::Integer(right)) => left == right, - (ValueData::List(left), ValueData::List(right)) => left == right, - (ValueData::Map(left), ValueData::Map(right)) => left == right, - (ValueData::Range(left), ValueData::Range(right)) => left == right, - (ValueData::String(left), ValueData::String(right)) => left == right, - (ValueData::Struct(left), ValueData::Struct(right)) => left == right, - (ValueData::Tuple(left), ValueData::Tuple(right)) => left == right, - _ => false, - } - } -} - -impl PartialOrd for ValueData { +impl PartialOrd for Primitive { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for ValueData { +impl Ord for Primitive { fn cmp(&self, other: &Self) -> Ordering { match (self, other) { - (ValueData::Boolean(left), ValueData::Boolean(right)) => left.cmp(right), - (ValueData::Boolean(_), _) => Ordering::Greater, - (ValueData::Byte(left), ValueData::Byte(right)) => left.cmp(right), - (ValueData::Byte(_), _) => Ordering::Greater, - (ValueData::Character(left), ValueData::Character(right)) => left.cmp(right), - (ValueData::Character(_), _) => Ordering::Greater, - (ValueData::Float(left), ValueData::Float(right)) => left.partial_cmp(right).unwrap(), - (ValueData::Float(_), _) => Ordering::Greater, - (ValueData::Function(left), ValueData::Function(right)) => left.cmp(right), - (ValueData::Function(_), _) => Ordering::Greater, - (ValueData::Integer(left), ValueData::Integer(right)) => left.cmp(right), - (ValueData::Integer(_), _) => Ordering::Greater, - (ValueData::List(left), ValueData::List(right)) => left.cmp(right), - (ValueData::List(_), _) => Ordering::Greater, - (ValueData::Range(left), ValueData::Range(right)) => left.cmp(right), - (ValueData::Range(_), _) => Ordering::Greater, - (ValueData::String(left), ValueData::String(right)) => left.cmp(right), - (ValueData::String(_), _) => Ordering::Greater, - (ValueData::Struct(left), ValueData::Struct(right)) => left.cmp(right), - (ValueData::Struct(_), _) => Ordering::Greater, - (ValueData::Tuple(left), ValueData::Tuple(right)) => left.cmp(right), - _ => Ordering::Greater, - } - } -} - -impl Serialize for ValueData { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - match self { - ValueData::Boolean(boolean) => serializer.serialize_bool(*boolean), - ValueData::Byte(byte) => serializer.serialize_u8(*byte), - ValueData::Character(character) => serializer.serialize_char(*character), - ValueData::Enum(r#emum) => r#emum.serialize(serializer), - ValueData::Float(float) => serializer.serialize_f64(*float), - ValueData::Function(function) => function.serialize(serializer), - ValueData::Integer(integer) => serializer.serialize_i64(*integer), - ValueData::List(list) => list.serialize(serializer), - ValueData::Map(pairs) => { - let mut ser = serializer.serialize_map(Some(pairs.len()))?; - - for (key, value) in pairs { - ser.serialize_entry(key, value)?; + (Primitive::Boolean(left), Primitive::Boolean(right)) => left.cmp(right), + (Primitive::Boolean(_), _) => Ordering::Greater, + (Primitive::Byte(left), Primitive::Byte(right)) => left.cmp(right), + (Primitive::Byte(_), _) => Ordering::Greater, + (Primitive::Character(left), Primitive::Character(right)) => left.cmp(right), + (Primitive::Character(_), _) => Ordering::Greater, + (Primitive::Float(left), Primitive::Float(right)) => { + if left.is_nan() && right.is_nan() { + Ordering::Equal + } else if left.is_nan() { + Ordering::Less + } else if right.is_nan() { + Ordering::Greater + } else { + left.partial_cmp(right).unwrap() } - - ser.end() } - ValueData::Range(range) => range.serialize(serializer), - ValueData::String(string) => serializer.serialize_str(string), - ValueData::Struct(r#struct) => r#struct.serialize(serializer), - ValueData::Tuple(tuple) => tuple.serialize(serializer), + (Primitive::Float(_), _) => Ordering::Greater, + (Primitive::Function(left), Primitive::Function(right)) => left.cmp(right), + (Primitive::Function(_), _) => Ordering::Greater, + (Primitive::Integer(left), Primitive::Integer(right)) => left.cmp(right), + (Primitive::Integer(_), _) => Ordering::Greater, + (Primitive::Range(left), Primitive::Range(right)) => left.cmp(right), + (Primitive::Range(_), _) => Ordering::Greater, + (Primitive::String(left), Primitive::String(right)) => left.cmp(right), + (Primitive::String(_), _) => Ordering::Greater, } } } -impl<'de> Deserialize<'de> for ValueData { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct ValueDataVisitor; - - impl<'de> Visitor<'de> for ValueDataVisitor { - type Value = ValueData; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a value") - } - - fn visit_bool(self, value: bool) -> Result { - Ok(ValueData::Boolean(value)) - } - - fn visit_u8(self, value: u8) -> Result { - Ok(ValueData::Byte(value)) - } - - fn visit_char(self, value: char) -> Result { - Ok(ValueData::Character(value)) - } - - fn visit_f64(self, value: f64) -> Result { - Ok(ValueData::Float(value)) - } - - fn visit_i64(self, value: i64) -> Result { - Ok(ValueData::Integer(value)) - } - - fn visit_str(self, value: &str) -> Result { - Ok(ValueData::String(value.to_string())) - } - } - - deserializer.deserialize_any(ValueDataVisitor) - } -} - #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Function { - body: Chunk, -} - -impl Function { - pub fn body(&self) -> &Chunk { - &self.body - } - - pub fn call( - self, - _type_arguments: Option>, - _value_arguments: Option>, - ) -> Result, String> { - todo!() - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -pub enum Struct { - Unit { - name: Identifier, - }, - Tuple { - name: Identifier, - fields: Vec, - }, - Fields { - name: Identifier, - fields: HashMap, - }, -} - -impl PartialOrd for Struct { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Struct { - fn cmp(&self, other: &Self) -> Ordering { - match (self, other) { - (Struct::Unit { name: left }, Struct::Unit { name: right }) => left.cmp(right), - (Struct::Unit { .. }, _) => Ordering::Greater, - ( - Struct::Tuple { - name: left_name, - fields: left_fields, - }, - Struct::Tuple { - name: right_name, - fields: right_fields, - }, - ) => { - let type_cmp = left_name.cmp(right_name); - - if type_cmp != Ordering::Equal { - return type_cmp; - } - - left_fields.cmp(right_fields) - } - (Struct::Tuple { .. }, _) => Ordering::Greater, - ( - Struct::Fields { - name: left_name, - fields: left_fields, - }, - Struct::Fields { - name: right_name, - fields: right_fields, - }, - ) => { - let type_cmp = left_name.cmp(right_name); - - if type_cmp != Ordering::Equal { - return type_cmp; - } - - left_fields.iter().cmp(right_fields.iter()) - } - (Struct::Fields { .. }, _) => Ordering::Greater, - } - } -} - -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, value)) in fields.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; - } - - write!(f, "{}: {}", identifier, value)?; - } - - write!(f, " }}") - } - } - } + pub body: Chunk, } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] @@ -1785,127 +841,150 @@ impl Ord for RangeValue { } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Enum { - pub r#type: EnumType, - pub name: Identifier, - pub variant_data: Struct, +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +pub enum Object { + List { start: u8, end: u8 }, } -impl Display for Enum { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - let Enum { - name, variant_data, .. - } = self; +impl Object { + fn display(&self, vm: &Vm, position: Span) -> Result { + match self { + Object::List { start, end } => { + let mut display = String::from("["); + let (start, end) = (*start, *end); - match &variant_data { - Struct::Unit { name: variant_name } => write!(f, "{name}::{variant_name}"), - Struct::Tuple { - name: variant_name, - fields, - } => { - write!(f, "{name}::{variant_name}(")?; - - for (index, field) in fields.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; + for register in start..=end { + if register > start { + display.push_str(", "); } - write!(f, "{}", field)?; + let value_display = match vm.get(register, position) { + Ok(value) => value.display(vm, position)?, + Err(error) => { + return Err(ValueError::CannotDisplay { + value: Value::Object(self.clone()), + vm_error: Box::new(error), + }) + } + }; + + display.push_str(&value_display); } - write!(f, ")") - } - Struct::Fields { - name: variant_name, - fields, - } => { - write!(f, "{name}::{variant_name} {{ ")?; + display.push(']'); - for (index, (identifier, value)) in fields.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; - } - - write!(f, "{}: {}", identifier, value)?; - } - - write!(f, " }}") + Ok(display) } } } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq)] pub enum ValueError { CannotAdd(Value, Value), CannotAnd(Value, Value), + CannotDisplay { + value: Value, + vm_error: Box, + }, CannotDivide(Value, Value), - CannotGreaterThan(Value, Value), - CannotGreaterThanOrEqual(Value, Value), - CannotIndex { value: Value, index: Value }, CannotLessThan(Value, Value), CannotLessThanOrEqual(Value, Value), - CannotMakeMutable, CannotModulo(Value, Value), CannotMultiply(Value, Value), - CannotMutate(Value), CannotNegate(Value), CannotNot(Value), CannotSubtract(Value, Value), CannotOr(Value, Value), - IndexOutOfBounds { value: Value, index: i64 }, } 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), - ValueError::CannotAnd(left, right) => write!( - f, - "Cannot use logical and operation on {} and {}", - left, right - ), - ValueError::CannotDivide(left, right) => { - write!(f, "Cannot divide {} by {}", left, right) + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let get_value_display = |value: &Value| -> String { + match value { + Value::Primitive(primitive) => primitive.to_string(), + Value::Object(_) => "Object".to_string(), } - ValueError::CannotIndex { value, index } => { - write!(f, "Cannot index {} with {}", value, index) + }; + + match self { + ValueError::CannotAdd(left, right) => { + let left_display = get_value_display(left); + let right_display = get_value_display(right); + + write!(f, "Cannot add {} and {}", left_display, right_display) + } + ValueError::CannotAnd(left, right) => { + let left_display = get_value_display(left); + let right_display = get_value_display(right); + + write!( + f, + "Cannot use logical and operation on {} and {}", + left_display, right_display + ) + } + ValueError::CannotDisplay { value, vm_error } => { + let value_display = get_value_display(value); + + write!(f, "Cannot display {}: {:?}", value_display, vm_error) + } + ValueError::CannotDivide(left, right) => { + let left_display = get_value_display(left); + let right_display = get_value_display(right); + + write!(f, "Cannot divide {} by {}", left_display, right_display) + } + ValueError::CannotLessThan(left, right) => { + let left_display = get_value_display(left); + let right_display = get_value_display(right); + + write!(f, "Cannot compare {} and {}", left_display, right_display) + } + ValueError::CannotLessThanOrEqual(left, right) => { + let left_display = get_value_display(left); + let right_display = get_value_display(right); + + write!(f, "Cannot compare {} and {}", left_display, right_display) } ValueError::CannotModulo(left, right) => { - write!(f, "Cannot modulo {} by {}", left, right) + let left_display = get_value_display(left); + let right_display = get_value_display(right); + + write!(f, "Cannot modulo {} by {}", left_display, right_display) } ValueError::CannotMultiply(left, right) => { - write!(f, "Cannot multiply {} and {}", left, right) + let left_display = get_value_display(left); + let right_display = get_value_display(right); + + write!(f, "Cannot multiply {} by {}", left_display, right_display) + } + ValueError::CannotNegate(value) => { + let value_display = get_value_display(value); + + write!(f, "Cannot negate {}", value_display) } - ValueError::CannotMakeMutable => write!( - f, - "Failed to make mutable value because the value has an immutable reference to it" - ), - ValueError::CannotMutate(value) => write!(f, "Cannot mutate {}", value), - ValueError::CannotNegate(value) => write!(f, "Cannot negate {}", value), ValueError::CannotNot(value) => { - write!(f, "Cannot use logical not operation on {}", value) + let value_display = get_value_display(value); + + write!(f, "Cannot use logical not operation on {}", value_display) } ValueError::CannotSubtract(left, right) => { - write!(f, "Cannot subtract {} and {}", left, right) - } - ValueError::CannotLessThan(left, right) - | ValueError::CannotLessThanOrEqual(left, right) - | ValueError::CannotGreaterThan(left, right) - | ValueError::CannotGreaterThanOrEqual(left, right) => { - write!(f, "Cannot compare {} and {}", left, right) + let left_display = get_value_display(left); + let right_display = get_value_display(right); + + write!(f, "Cannot subtract {} from {}", right_display, left_display) } ValueError::CannotOr(left, right) => { + let left_display = get_value_display(left); + let right_display = get_value_display(right); + write!( f, "Cannot use logical or operation on {} and {}", - left, right + left_display, right_display ) } - ValueError::IndexOutOfBounds { value, index } => { - write!(f, "{} does not have an index of {}", value, index) - } } } } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 08fe6c0..24b24e2 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -1,8 +1,8 @@ use std::mem::replace; use crate::{ - parse, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, Operation, Span, - Value, ValueError, + parse, value::Primitive, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, + Operation, Span, Value, ValueError, }; pub fn run(source: &str) -> Result, DustError> { @@ -116,20 +116,9 @@ impl Vm { let to_register = instruction.a(); let first_register = instruction.b(); let last_register = instruction.c(); - let length = last_register - first_register + 1; - let mut list = Vec::with_capacity(length as usize); + let value = Value::list(first_register, last_register); - for register_index in first_register..=last_register { - let value = match self.take(register_index, to_register, position) { - Ok(value) => value, - Err(VmError::EmptyRegister { .. }) => continue, - Err(error) => return Err(error), - }; - - list.push(value); - } - - self.set(to_register, Value::list(list), position)?; + self.set(to_register, value, position)?; } Operation::DefineLocal => { let from_register = instruction.a(); @@ -211,10 +200,14 @@ impl Vm { let register = instruction.a(); let test_value = instruction.c_as_boolean(); let value = self.get(register, position)?; - let boolean = value.as_boolean().ok_or_else(|| VmError::ExpectedBoolean { - found: value.clone(), - position, - })?; + let boolean = if let Value::Primitive(Primitive::Boolean(boolean)) = value { + *boolean + } else { + return Err(VmError::ExpectedBoolean { + found: value.clone(), + position, + }); + }; if boolean != test_value { self.ip += 1; @@ -226,12 +219,14 @@ impl Vm { let test_value = instruction.c_as_boolean(); let borrowed_value = self.get(argument, position)?; let boolean = - borrowed_value - .as_boolean() - .ok_or_else(|| VmError::ExpectedBoolean { + if let Value::Primitive(Primitive::Boolean(boolean)) = borrowed_value { + *boolean + } else { + return Err(VmError::ExpectedBoolean { found: borrowed_value.clone(), position, - })?; + }); + }; if boolean == test_value { let value = self.take(argument, to_register, position)?; @@ -248,15 +243,18 @@ impl Vm { ); let (left, right) = get_arguments(self, instruction, position)?; - - let boolean = left + let equal_result = left .equal(right) - .map_err(|error| VmError::Value { error, position })? - .as_boolean() - .ok_or_else(|| VmError::ExpectedBoolean { - found: left.clone(), - position, - })?; + .map_err(|error| VmError::Value { error, position })?; + let boolean = + if let Value::Primitive(Primitive::Boolean(boolean)) = equal_result { + boolean + } else { + return Err(VmError::ExpectedBoolean { + found: equal_result.clone(), + position, + }); + }; let compare_to = instruction.a_as_boolean(); if boolean == compare_to { @@ -281,14 +279,18 @@ impl Vm { ); let (left, right) = get_arguments(self, instruction, position)?; - let boolean = left + let less_result = left .less_than(right) - .map_err(|error| VmError::Value { error, position })? - .as_boolean() - .ok_or_else(|| VmError::ExpectedBoolean { - found: left.clone(), + .map_err(|error| VmError::Value { error, position })?; + let boolean = if let Value::Primitive(Primitive::Boolean(boolean)) = less_result + { + boolean + } else { + return Err(VmError::ExpectedBoolean { + found: less_result.clone(), position, - })?; + }); + }; let compare_to = instruction.a_as_boolean(); if boolean == compare_to { @@ -313,14 +315,19 @@ impl Vm { ); let (left, right) = get_arguments(self, instruction, position)?; - let boolean = left + let less_or_equal_result = left .less_than_or_equal(right) - .map_err(|error| VmError::Value { error, position })? - .as_boolean() - .ok_or_else(|| VmError::ExpectedBoolean { - found: left.clone(), + .map_err(|error| VmError::Value { error, position })?; + let boolean = if let Value::Primitive(Primitive::Boolean(boolean)) = + less_or_equal_result + { + boolean + } else { + return Err(VmError::ExpectedBoolean { + found: less_or_equal_result.clone(), position, - })?; + }); + }; let compare_to = instruction.a_as_boolean(); if boolean == compare_to { @@ -457,7 +464,7 @@ impl Vm { }) } - fn get(&self, index: u8, position: Span) -> Result<&Value, VmError> { + pub fn get(&self, index: u8, position: Span) -> Result<&Value, VmError> { let index = index as usize; let register = self .stack diff --git a/dust-lang/tests/expressions.rs b/dust-lang/tests/expressions.rs index 53207bc..e6ae59c 100644 --- a/dust-lang/tests/expressions.rs +++ b/dust-lang/tests/expressions.rs @@ -506,14 +506,7 @@ fn list() { )), ); - assert_eq!( - run(source), - Ok(Some(Value::list(vec![ - Value::integer(1), - Value::integer(2), - Value::integer(3) - ]))) - ); + assert_eq!(run(source), Ok(Some(Value::list(0, 2)))); } #[test] @@ -553,13 +546,7 @@ fn list_with_complex_expression() { )), ); - assert_eq!( - run(source), - Ok(Some(Value::list(vec![ - Value::integer(1), - Value::integer(-15) - ]))) - ); + assert_eq!(run(source), Ok(Some(Value::list(0, 3)))); } #[test] @@ -591,14 +578,7 @@ fn list_with_simple_expression() { )), ); - assert_eq!( - run(source), - Ok(Some(Value::list(vec![ - Value::integer(1), - Value::integer(5), - Value::integer(4) - ]))) - ); + assert_eq!(run(source), Ok(Some(Value::list(0, 2)))); } #[test]