From 23782c37a34c1c23aa9a2024ca3ff582156e4ac6 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 23 Aug 2024 03:04:11 -0400 Subject: [PATCH] Complete value overhaul --- dust-lang/src/analyzer.rs | 4 +- dust-lang/src/constructor.rs | 6 +- dust-lang/src/context.rs | 2 +- dust-lang/src/core_library.rs | 6 +- dust-lang/src/value.rs | 382 +++++++++++++++++++++++----------- dust-lang/src/vm.rs | 112 +++++----- 6 files changed, 322 insertions(+), 190 deletions(-) diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index c41124d..f5ef596 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -17,8 +17,8 @@ use crate::{ PrimitiveValueExpression, RangeExpression, Span, Statement, StructDefinition, StructExpression, TupleAccessExpression, }, - core_library, parse, Context, ContextError, DustError, Expression, Identifier, Rangeable, - RangeableType, StructType, Type, + core_library, parse, Context, ContextError, DustError, Expression, Identifier, RangeableType, + StructType, Type, }; /// Analyzes the abstract syntax tree for errors. diff --git a/dust-lang/src/constructor.rs b/dust-lang/src/constructor.rs index 8e2eb91..3d8d7c5 100644 --- a/dust-lang/src/constructor.rs +++ b/dust-lang/src/constructor.rs @@ -31,7 +31,7 @@ pub struct UnitConstructor { impl UnitConstructor { pub fn construct(self) -> Value { - Value::Struct(Struct::Unit { name: self.name }) + Value::r#struct(Struct::Unit { name: self.name }) } } @@ -42,7 +42,7 @@ pub struct TupleConstructor { impl TupleConstructor { pub fn construct(self, fields: Vec) -> Value { - Value::Struct(Struct::Tuple { + Value::r#struct(Struct::Tuple { name: self.name, fields, }) @@ -56,7 +56,7 @@ pub struct FieldsConstructor { impl FieldsConstructor { pub fn construct(self, fields: HashMap) -> Value { - Value::Struct(Struct::Fields { + Value::r#struct(Struct::Fields { name: self.name, fields, }) diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index c2e3cc1..6d71a07 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -347,7 +347,7 @@ mod tests { assert_eq!( run_with_context(source, context.clone()), - Ok(Some(Value::Integer(15))) + Ok(Some(Value::integer(15))) ); assert_eq!(context.association_count().unwrap(), 0); diff --git a/dust-lang/src/core_library.rs b/dust-lang/src/core_library.rs index 6c771a2..b634d5e 100644 --- a/dust-lang/src/core_library.rs +++ b/dust-lang/src/core_library.rs @@ -10,7 +10,7 @@ pub fn core_library<'a>() -> &'a Context { ( Identifier::new("to_string"), ( - ContextData::VariableValue(Value::Function(Function::BuiltIn( + ContextData::VariableValue(Value::function(Function::BuiltIn( BuiltInFunction::ToString, ))), (0, 0), @@ -19,7 +19,7 @@ pub fn core_library<'a>() -> &'a Context { ( Identifier::new("read_line"), ( - ContextData::VariableValue(Value::Function(Function::BuiltIn( + ContextData::VariableValue(Value::function(Function::BuiltIn( BuiltInFunction::ReadLine, ))), (0, 0), @@ -28,7 +28,7 @@ pub fn core_library<'a>() -> &'a Context { ( Identifier::new("write_line"), ( - ContextData::VariableValue(Value::Function(Function::BuiltIn( + ContextData::VariableValue(Value::function(Function::BuiltIn( BuiltInFunction::WriteLine, ))), (0, 0), diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index 882df67..a153d1a 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -5,12 +5,11 @@ use std::{ error::Error, fmt::{self, Display, Formatter}, ops::{Range, RangeInclusive}, - ptr::read, sync::{Arc, RwLock}, }; use serde::{ - de::{self, EnumAccess, MapAccess, SeqAccess, Visitor}, + de::{self, MapAccess, SeqAccess, Visitor}, ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer, }; @@ -25,30 +24,29 @@ use crate::{ /// Each type of value has a corresponding constructor, here are some simple examples: /// /// ``` -/// # use dust_lang::ValueData; -/// let boolean = ValueData::boolean(true); -/// let float = ValueData::float(3.14); -/// let integer = ValueData::integer(42); -/// let string = ValueData::string("Hello, world!"); +/// # 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::ValueData; -/// let list = ValueData::list(vec![ -/// ValueData::integer(1), -/// ValueData::integer(2), -/// ValueData::integer(3), +/// # 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; /// # use dust_lang::*; -/// let value = ValueData::integer(42); +/// let value = Value::integer(42); /// /// assert_eq!(value.r#type(), Type::Integer); /// ``` @@ -76,8 +74,8 @@ impl Value { Value::Raw(ValueData::Float(value)) } - pub fn integer(value: i64) -> Self { - Value::Raw(ValueData::Integer(value)) + pub fn integer>(into_i64: T) -> Self { + Value::Raw(ValueData::Integer(into_i64.into())) } pub fn string(to_string: T) -> Self { @@ -88,8 +86,8 @@ impl Value { Value::Raw(ValueData::List(value)) } - pub fn map(value: HashMap) -> Self { - Value::Raw(ValueData::Map(value)) + pub fn map>>(into_map: T) -> Self { + Value::Raw(ValueData::Map(into_map.into())) } pub fn mutable(value: Value) -> Self { @@ -104,12 +102,12 @@ impl Value { Value::Raw(ValueData::Function(value)) } - pub fn range>(start: T, end: T) -> Self { - Value::Raw(ValueData::Range(start.into()..end.into())) + pub fn range>(range: T) -> Self { + Value::Raw(ValueData::Range(range.into())) } - pub fn range_inclusive>(start: T, end: T) -> Self { - Value::Raw(ValueData::RangeInclusive(start.into()..=end.into())) + pub fn r#struct(value: Struct) -> Self { + Value::Raw(ValueData::Struct(value)) } pub fn reference(value: Value) -> Self { @@ -282,6 +280,40 @@ impl Value { 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(), @@ -354,7 +386,7 @@ impl Value { Value::Mutable(data) => &data.read().unwrap(), }; let new_data = left - .add(&right) + .add(right) .ok_or_else(|| ValueError::CannotAdd(self.clone(), other.clone()))?; *left = new_data; @@ -392,7 +424,7 @@ impl Value { Value::Mutable(data) => &data.read().unwrap(), }; let new_data = left - .subtract(&right) + .subtract(right) .ok_or_else(|| ValueError::CannotSubtract(self.clone(), other.clone()))?; *left = new_data; @@ -430,7 +462,7 @@ impl Value { Value::Mutable(data) => &data.read().unwrap(), }; let new_data = left - .multiply(&right) + .multiply(right) .ok_or_else(|| ValueError::CannotMultiply(self.clone(), other.clone()))?; *left = new_data; @@ -468,7 +500,7 @@ impl Value { Value::Mutable(data) => &data.read().unwrap(), }; let new_data = left - .divide(&right) + .divide(right) .ok_or_else(|| ValueError::CannotDivide(self.clone(), other.clone()))?; *left = new_data; @@ -506,7 +538,7 @@ impl Value { Value::Mutable(data) => &data.read().unwrap(), }; let new_data = left - .modulo(&right) + .modulo(right) .ok_or_else(|| ValueError::CannotModulo(self.clone(), other.clone()))?; *left = new_data; @@ -709,14 +741,18 @@ impl Eq for Value {} impl PartialEq for Value { fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Value::Raw(left), Value::Raw(right)) => left == right, - (Value::Reference(left), Value::Reference(right)) => left == right, - (Value::Mutable(left), Value::Mutable(right)) => { - *left.read().unwrap() == *right.read().unwrap() - } - _ => false, - } + 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 } } @@ -834,8 +870,7 @@ pub enum ValueData { Integer(i64), List(Vec), Map(HashMap), - Range(Range), - RangeInclusive(RangeInclusive), + Range(RangeValue), String(String), Struct(Struct), Tuple(Vec), @@ -875,16 +910,7 @@ impl ValueData { Type::Map { pairs } } - ValueData::Range(range) => Type::Range { - r#type: range.start.r#type(), - }, - ValueData::RangeInclusive(range_inclusive) => { - let rangeable_type = range_inclusive.start().r#type(); - - Type::Range { - r#type: rangeable_type, - } - } + ValueData::Range(range) => range.r#type(), ValueData::String(string) => Type::String { length: Some(string.len()), }, @@ -919,13 +945,13 @@ impl ValueData { } pub fn is_rangeable(&self) -> bool { - match self { + matches!( + self, ValueData::Integer(_) - | ValueData::Float(_) - | ValueData::Character(_) - | ValueData::Byte(_) => true, - _ => false, - } + | ValueData::Float(_) + | ValueData::Character(_) + | ValueData::Byte(_) + ) } pub fn add(&self, other: &ValueData) -> Option { @@ -1174,14 +1200,8 @@ impl Display for ValueData { write!(f, "]") } - ValueData::Range(Range { start, end }) => { - write!(f, "{start}..{end}") - } - ValueData::RangeInclusive(inclusive) => { - let start = inclusive.start(); - let end = inclusive.end(); - - write!(f, "{start}..={end}") + ValueData::Range(range_value) => { + write!(f, "{range_value}") } ValueData::String(string) => write!(f, "{string}"), ValueData::Struct(r#struct) => write!(f, "{struct}"), @@ -1216,7 +1236,6 @@ impl PartialEq for ValueData { (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::RangeInclusive(left), ValueData::RangeInclusive(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, @@ -1248,26 +1267,8 @@ impl Ord for ValueData { (ValueData::Integer(_), _) => Ordering::Greater, (ValueData::List(left), ValueData::List(right)) => left.cmp(right), (ValueData::List(_), _) => Ordering::Greater, - (ValueData::Range(left), ValueData::Range(right)) => { - let start_cmp = left.start.cmp(&right.start); - - if start_cmp.is_eq() { - left.end.cmp(&right.end) - } else { - start_cmp - } - } + (ValueData::Range(left), ValueData::Range(right)) => left.cmp(right), (ValueData::Range(_), _) => Ordering::Greater, - (ValueData::RangeInclusive(left), ValueData::RangeInclusive(right)) => { - let start_cmp = left.start().cmp(right.start()); - - if start_cmp.is_eq() { - left.end().cmp(right.end()) - } else { - start_cmp - } - } - (ValueData::RangeInclusive(_), _) => Ordering::Greater, (ValueData::String(left), ValueData::String(right)) => left.cmp(right), (ValueData::String(_), _) => Ordering::Greater, (ValueData::Struct(left), ValueData::Struct(right)) => left.cmp(right), @@ -1302,7 +1303,6 @@ impl Serialize for ValueData { ser.end() } ValueData::Range(range) => range.serialize(serializer), - ValueData::RangeInclusive(inclusive) => inclusive.serialize(serializer), ValueData::String(string) => serializer.serialize_str(string), ValueData::Struct(r#struct) => r#struct.serialize(serializer), ValueData::Tuple(tuple) => tuple.serialize(serializer), @@ -1561,84 +1561,212 @@ impl Display for Struct { } } -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] -pub enum Rangeable { - Byte(u8), - Character(char), - Float(f64), - Integer(i64), +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum RangeValue { + ByteRange(Range), + ByteRangeInclusive(RangeInclusive), + CharacterRange(Range), + CharacterRangeInclusive(RangeInclusive), + FloatRange(Range), + FloatRangeInclusive(RangeInclusive), + IntegerRange(Range), + IntegerRangeInclusive(RangeInclusive), } -impl From for Rangeable { - fn from(value: u8) -> Self { - Rangeable::Byte(value) +impl RangeValue { + pub fn r#type(&self) -> Type { + let inner_type = match self { + RangeValue::ByteRange(_) => RangeableType::Byte, + RangeValue::ByteRangeInclusive(_) => RangeableType::Byte, + RangeValue::CharacterRange(_) => RangeableType::Character, + RangeValue::CharacterRangeInclusive(_) => RangeableType::Character, + RangeValue::FloatRange(_) => RangeableType::Float, + RangeValue::FloatRangeInclusive(_) => RangeableType::Float, + RangeValue::IntegerRange(_) => RangeableType::Integer, + RangeValue::IntegerRangeInclusive(_) => RangeableType::Integer, + }; + + Type::Range { r#type: inner_type } } } -impl From for Rangeable { - fn from(value: char) -> Self { - Rangeable::Character(value) +impl From> for RangeValue { + fn from(range: Range) -> Self { + RangeValue::ByteRange(range) } } -impl From for Rangeable { - fn from(value: f64) -> Self { - Rangeable::Float(value) +impl From> for RangeValue { + fn from(range: RangeInclusive) -> Self { + RangeValue::ByteRangeInclusive(range) } } -impl From for Rangeable { - fn from(value: i32) -> Self { - Rangeable::Integer(value as i64) +impl From> for RangeValue { + fn from(range: Range) -> Self { + RangeValue::CharacterRange(range) } } -impl From for Rangeable { - fn from(value: i64) -> Self { - Rangeable::Integer(value) +impl From> for RangeValue { + fn from(range: RangeInclusive) -> Self { + RangeValue::CharacterRangeInclusive(range) } } -impl Rangeable { - fn r#type(&self) -> RangeableType { - match self { - Rangeable::Byte(_) => RangeableType::Byte, - Rangeable::Character(_) => RangeableType::Character, - Rangeable::Float(_) => RangeableType::Float, - Rangeable::Integer(_) => RangeableType::Integer, - } +impl From> for RangeValue { + fn from(range: Range) -> Self { + RangeValue::FloatRange(range) } } -impl Display for Rangeable { +impl From> for RangeValue { + fn from(range: RangeInclusive) -> Self { + RangeValue::FloatRangeInclusive(range) + } +} + +impl From> for RangeValue { + fn from(range: Range) -> Self { + RangeValue::IntegerRange(range.start as i64..range.end as i64) + } +} + +impl From> for RangeValue { + fn from(range: RangeInclusive) -> Self { + RangeValue::IntegerRangeInclusive(*range.start() as i64..=*range.end() as i64) + } +} + +impl From> for RangeValue { + fn from(range: Range) -> Self { + RangeValue::IntegerRange(range) + } +} + +impl From> for RangeValue { + fn from(range: RangeInclusive) -> Self { + RangeValue::IntegerRangeInclusive(range) + } +} + +impl Display for RangeValue { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - Rangeable::Byte(byte) => write!(f, "{byte}"), - Rangeable::Character(character) => write!(f, "{character}"), - Rangeable::Float(float) => write!(f, "{float}"), - Rangeable::Integer(integer) => write!(f, "{integer}"), + RangeValue::ByteRange(range) => write!(f, "{}..{}", range.start, range.end), + RangeValue::ByteRangeInclusive(range) => { + write!(f, "{}..={}", range.start(), range.end()) + } + RangeValue::CharacterRange(range) => write!(f, "{}..{}", range.start, range.end), + RangeValue::CharacterRangeInclusive(range) => { + write!(f, "{}..={}", range.start(), range.end()) + } + RangeValue::FloatRange(range) => write!(f, "{}..{}", range.start, range.end), + RangeValue::FloatRangeInclusive(range) => { + write!(f, "{}..={}", range.start(), range.end()) + } + RangeValue::IntegerRange(range) => write!(f, "{}..{}", range.start, range.end), + RangeValue::IntegerRangeInclusive(range) => { + write!(f, "{}..={}", range.start(), range.end()) + } } } } -impl Eq for Rangeable {} +impl Eq for RangeValue {} -impl PartialOrd for Rangeable { +impl PartialOrd for RangeValue { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for Rangeable { +impl Ord for RangeValue { fn cmp(&self, other: &Self) -> Ordering { match (self, other) { - (Rangeable::Byte(left), Rangeable::Byte(right)) => left.cmp(right), - (Rangeable::Character(left), Rangeable::Character(right)) => left.cmp(right), - (Rangeable::Float(left), Rangeable::Float(right)) => { - left.to_bits().cmp(&right.to_bits()) + (RangeValue::ByteRange(left), RangeValue::ByteRange(right)) => { + let start_cmp = left.start.cmp(&right.start); + + if start_cmp != Ordering::Equal { + start_cmp + } else { + left.end.cmp(&right.end) + } } - (Rangeable::Integer(left), Rangeable::Integer(right)) => left.cmp(right), - _ => unreachable!(), + (RangeValue::ByteRange(_), _) => Ordering::Greater, + (RangeValue::ByteRangeInclusive(left), RangeValue::ByteRangeInclusive(right)) => { + let start_cmp = left.start().cmp(right.start()); + + if start_cmp != Ordering::Equal { + start_cmp + } else { + left.end().cmp(right.end()) + } + } + (RangeValue::ByteRangeInclusive(_), _) => Ordering::Greater, + (RangeValue::CharacterRange(left), RangeValue::CharacterRange(right)) => { + let start_cmp = left.start.cmp(&right.start); + + if start_cmp != Ordering::Equal { + start_cmp + } else { + left.end.cmp(&right.end) + } + } + (RangeValue::CharacterRange(_), _) => Ordering::Greater, + ( + RangeValue::CharacterRangeInclusive(left), + RangeValue::CharacterRangeInclusive(right), + ) => { + let start_cmp = left.start().cmp(right.start()); + + if start_cmp != Ordering::Equal { + start_cmp + } else { + left.end().cmp(right.end()) + } + } + (RangeValue::CharacterRangeInclusive(_), _) => Ordering::Greater, + (RangeValue::FloatRange(left), RangeValue::FloatRange(right)) => { + let start_cmp = left.start.to_bits().cmp(&right.start.to_bits()); + + if start_cmp != Ordering::Equal { + start_cmp + } else { + left.end.to_bits().cmp(&right.end.to_bits()) + } + } + (RangeValue::FloatRange(_), _) => Ordering::Greater, + (RangeValue::FloatRangeInclusive(left), RangeValue::FloatRangeInclusive(right)) => { + let start_cmp = left.start().to_bits().cmp(&right.start().to_bits()); + + if start_cmp != Ordering::Equal { + start_cmp + } else { + left.end().to_bits().cmp(&right.end().to_bits()) + } + } + (RangeValue::FloatRangeInclusive(_), _) => Ordering::Greater, + (RangeValue::IntegerRange(left), RangeValue::IntegerRange(right)) => { + let start_cmp = left.start.cmp(&right.start); + + if start_cmp != Ordering::Equal { + start_cmp + } else { + left.end.cmp(&right.end) + } + } + (RangeValue::IntegerRange(_), _) => Ordering::Greater, + (RangeValue::IntegerRangeInclusive(left), RangeValue::IntegerRangeInclusive(right)) => { + let start_cmp = left.start().cmp(right.start()); + + if start_cmp != Ordering::Equal { + start_cmp + } else { + left.end().cmp(right.end()) + } + } + (RangeValue::IntegerRangeInclusive(_), _) => Ordering::Greater, } } } @@ -1745,6 +1873,10 @@ impl Display for ValueError { "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) + } ValueError::CannotSubtract(left, right) => { write!(f, "Cannot subtract {} and {}", left, right) } diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 0280f2e..5edeb50 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -386,16 +386,16 @@ impl Vm { match (start_data, end_data) { (ValueData::Byte(start), ValueData::Byte(end)) => { - Ok(Evaluation::Return(Some(Value::range(start, end)))) + Ok(Evaluation::Return(Some(Value::range(start..end)))) } (ValueData::Character(start), ValueData::Character(end)) => { - Ok(Evaluation::Return(Some(Value::range(start, end)))) + Ok(Evaluation::Return(Some(Value::range(start..end)))) } (ValueData::Float(start), ValueData::Float(end)) => { - Ok(Evaluation::Return(Some(Value::range(start, end)))) + Ok(Evaluation::Return(Some(Value::range(start..end)))) } (ValueData::Integer(start), ValueData::Integer(end)) => { - Ok(Evaluation::Return(Some(Value::range(start, end)))) + Ok(Evaluation::Return(Some(Value::range(start..end)))) } _ => Err(RuntimeError::InvalidRange { start_position, @@ -426,16 +426,16 @@ impl Vm { match (start_data, end_data) { (ValueData::Byte(start), ValueData::Byte(end)) => { - Ok(Evaluation::Return(Some(Value::range_inclusive(start, end)))) + Ok(Evaluation::Return(Some(Value::range(start..=end)))) } (ValueData::Character(start), ValueData::Character(end)) => { - Ok(Evaluation::Return(Some(Value::range_inclusive(start, end)))) + Ok(Evaluation::Return(Some(Value::range(start..=end)))) } (ValueData::Float(start), ValueData::Float(end)) => { - Ok(Evaluation::Return(Some(Value::range_inclusive(start, end)))) + Ok(Evaluation::Return(Some(Value::range(start..=end)))) } (ValueData::Integer(start), ValueData::Integer(end)) => { - Ok(Evaluation::Return(Some(Value::range_inclusive(start, end)))) + Ok(Evaluation::Return(Some(Value::range(start..=end)))) } _ => Err(RuntimeError::InvalidRange { start_position, @@ -1404,14 +1404,14 @@ mod tests { fn break_loop() { let input = "let mut x = 0; loop { x += 1; if x == 10 { break; } } x"; - assert_eq!(run(input), Ok(Some(Value::mutable(Value::Integer(10))))); + assert_eq!(run(input), Ok(Some(Value::mutable(Value::integer(10))))); } #[test] fn string_index() { let input = "'foo'[0]"; - assert_eq!(run(input), Ok(Some(Value::Character('f')))); + assert_eq!(run(input), Ok(Some(Value::character('f')))); } #[test] @@ -1421,8 +1421,8 @@ mod tests { assert_eq!( run(input), Ok(Some(Value::map([ - (Identifier::new("foo"), Value::Integer(42)), - (Identifier::new("bar"), Value::Float(4.2)) + (Identifier::new("foo"), Value::integer(42)), + (Identifier::new("bar"), Value::float(4.2)) ]))) ); } @@ -1431,7 +1431,7 @@ mod tests { fn async_block() { let input = "let mut x = 1; async { x += 1; x -= 1; } x"; - assert_eq!(run(input), Ok(Some(Value::mutable(Value::Integer(1))))); + assert_eq!(run(input), Ok(Some(Value::mutable(Value::integer(1))))); } #[test] @@ -1440,11 +1440,11 @@ mod tests { assert_eq!( run(input), - Ok(Some(Value::Struct(Struct::Fields { + Ok(Some(Value::r#struct(Struct::Fields { name: Identifier::new("Foo"), fields: HashMap::from([ - (Identifier::new("bar"), Value::Integer(42)), - (Identifier::new("baz"), Value::Float(4.0)) + (Identifier::new("bar"), Value::integer(42)), + (Identifier::new("baz"), Value::float(4.0)) ]) }))) ); @@ -1460,9 +1460,9 @@ mod tests { assert_eq!( run(input), - Ok(Some(Value::Struct(Struct::Tuple { + Ok(Some(Value::r#struct(Struct::Tuple { name: Identifier::new("Foo"), - fields: vec![Value::Integer(42)] + fields: vec![Value::integer(42)] }))) ) } @@ -1473,9 +1473,9 @@ mod tests { assert_eq!( run(input), - Ok(Some(Value::Struct(Struct::Tuple { + Ok(Some(Value::r#struct(Struct::Tuple { name: Identifier::new("Foo"), - fields: vec![Value::Integer(42)] + fields: vec![Value::integer(42)] }))) ); } @@ -1490,7 +1490,7 @@ mod tests { assert_eq!( run(input), - Ok(Some(Value::Struct(Struct::Unit { + Ok(Some(Value::r#struct(Struct::Unit { name: Identifier::new("Foo") }))) ) @@ -1502,7 +1502,7 @@ mod tests { assert_eq!( run(input), - Ok(Some(Value::Struct(Struct::Unit { + Ok(Some(Value::r#struct(Struct::Unit { name: Identifier::new("Foo") }))) ); @@ -1512,7 +1512,7 @@ mod tests { fn list_index_nested() { let input = "[[1, 2], [42, 4], [5, 6]][1][0]"; - assert_eq!(run(input), Ok(Some(Value::Integer(42)))); + assert_eq!(run(input), Ok(Some(Value::integer(42)))); } #[test] @@ -1521,9 +1521,9 @@ mod tests { assert_eq!( run(input), - Ok(Some(Value::List(vec![ - Value::Integer(2), - Value::Integer(3) + Ok(Some(Value::list(vec![ + Value::integer(2), + Value::integer(3) ]))) ); } @@ -1532,35 +1532,35 @@ mod tests { fn range() { let input = "1..5"; - assert_eq!(run(input), Ok(Some(Value::range(1, 5)))); + assert_eq!(run(input), Ok(Some(Value::range(1..5)))); } #[test] fn negate_expression() { let input = "let x = -42; -x"; - assert_eq!(run(input), Ok(Some(Value::Integer(42)))); + assert_eq!(run(input), Ok(Some(Value::integer(42)))); } #[test] fn not_expression() { let input = "!(1 == 2 || 3 == 4 || 5 == 6)"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn list_index() { let input = "[1, 42, 3][1]"; - assert_eq!(run(input), Ok(Some(Value::Integer(42)))); + assert_eq!(run(input), Ok(Some(Value::integer(42)))); } #[test] fn map_property_access() { let input = "map { a = 42 }.a"; - assert_eq!(run(input), Ok(Some(Value::Integer(42)))); + assert_eq!(run(input), Ok(Some(Value::integer(42)))); } #[test] @@ -1588,7 +1588,7 @@ mod tests { fn if_else() { let input = "let x = if false { 1 } else { 2 }; x"; - assert_eq!(run(input), Ok(Some(Value::Integer(2)))); + assert_eq!(run(input), Ok(Some(Value::integer(2)))); } #[test] @@ -1602,167 +1602,167 @@ mod tests { fn if_else_if_else() { let input = "if false { 1 } else if false { 2 } else { 3 }"; - assert_eq!(run(input), Ok(Some(Value::Integer(3)))); + assert_eq!(run(input), Ok(Some(Value::integer(3)))); } #[test] fn while_loop() { let input = "let mut x = 0; while x < 5 { x += 1 } x"; - assert_eq!(run(input), Ok(Some(Value::mutable_from(5)))); + assert_eq!(run(input), Ok(Some(Value::integer(5)))); } #[test] fn subtract_assign() { let input = "let mut x = 1; x -= 1; x"; - assert_eq!(run(input), Ok(Some(Value::mutable_from(0)))); + assert_eq!(run(input), Ok(Some(Value::integer(0)))); } #[test] fn add_assign() { let input = "let mut x = 1; x += 1; x"; - assert_eq!(run(input), Ok(Some(Value::mutable_from(2)))); + assert_eq!(run(input), Ok(Some(Value::integer(2)))); } #[test] fn and() { let input = "true && true"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn or() { let input = "true || false"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn integer_equal() { let input = "42 == 42"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn modulo() { let input = "42 % 2"; - assert_eq!(run(input), Ok(Some(Value::Integer(0)))); + assert_eq!(run(input), Ok(Some(Value::integer(0)))); } #[test] fn divide() { let input = "42 / 2"; - assert_eq!(run(input), Ok(Some(Value::Integer(21)))); + assert_eq!(run(input), Ok(Some(Value::integer(21)))); } #[test] fn less_than() { let input = "2 < 3"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn less_than_or_equal() { let input = "42 <= 42"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn greater_than() { let input = "2 > 3"; - assert_eq!(run(input), Ok(Some(Value::Boolean(false)))); + assert_eq!(run(input), Ok(Some(Value::boolean(false)))); } #[test] fn greater_than_or_equal() { let input = "42 >= 42"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn integer_saturating_add() { let input = "9223372036854775807 + 1"; - assert_eq!(run(input), Ok(Some(Value::Integer(i64::MAX)))); + assert_eq!(run(input), Ok(Some(Value::integer(i64::MAX)))); } #[test] fn integer_saturating_sub() { let input = "-9223372036854775808 - 1"; - assert_eq!(run(input), Ok(Some(Value::Integer(i64::MIN)))); + assert_eq!(run(input), Ok(Some(Value::integer(i64::MIN)))); } #[test] fn multiply() { let input = "2 * 3"; - assert_eq!(run(input), Ok(Some(Value::Integer(6)))); + assert_eq!(run(input), Ok(Some(Value::integer(6)))); } #[test] fn boolean() { let input = "true"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn is_even() { let input = "42.is_even"; - assert_eq!(run(input), Ok(Some(Value::Boolean(true)))); + assert_eq!(run(input), Ok(Some(Value::boolean(true)))); } #[test] fn is_odd() { let input = "42.is_odd"; - assert_eq!(run(input), Ok(Some(Value::Boolean(false)))); + assert_eq!(run(input), Ok(Some(Value::boolean(false)))); } #[test] fn list_length() { let input = "[1, 2, 3].length"; - assert_eq!(run(input), Ok(Some(Value::Integer(3)))); + assert_eq!(run(input), Ok(Some(Value::integer(3)))); } #[test] fn string_length() { let input = "\"hello\".length"; - assert_eq!(run(input), Ok(Some(Value::Integer(5)))); + assert_eq!(run(input), Ok(Some(Value::integer(5)))); } #[test] fn map_length() { let input = "map { a = 42, b = 4.0 }.length"; - assert_eq!(run(input), Ok(Some(Value::Integer(2)))); + assert_eq!(run(input), Ok(Some(Value::integer(2)))); } #[test] fn add() { let input = "1 + 2"; - assert_eq!(run(input), Ok(Some(Value::Integer(3)))); + assert_eq!(run(input), Ok(Some(Value::integer(3)))); } #[test] fn add_multiple() { let input = "1 + 2 + 3"; - assert_eq!(run(input), Ok(Some(Value::Integer(6)))); + assert_eq!(run(input), Ok(Some(Value::integer(6)))); } }