Expand Value and Expression

This commit is contained in:
Jeff 2024-08-16 22:43:29 -04:00
parent 8ae453add7
commit 447643f315
6 changed files with 375 additions and 127 deletions

View File

@ -10,7 +10,9 @@ use std::{
}; };
use crate::{ use crate::{
ast::{AbstractSyntaxTree, LetStatement, Node, OperatorExpression, Statement}, ast::{
AbstractSyntaxTree, LetStatement, Node, OperatorExpression, Statement, StructDefinition,
},
parse, Context, DustError, Expression, Identifier, Span, Type, parse, Context, DustError, Expression, Identifier, Span, Type,
}; };
@ -89,8 +91,8 @@ impl<'a> Analyzer<'a> {
identifier.position, identifier.position,
); );
} else { } else {
return Err(AnalyzerError::UndefinedVariable { return Err(AnalyzerError::ExpectedValue {
identifier: identifier.clone(), actual: statement.clone(),
}); });
} }
@ -106,8 +108,8 @@ impl<'a> Analyzer<'a> {
identifier.position, identifier.position,
); );
} else { } else {
return Err(AnalyzerError::UndefinedVariable { return Err(AnalyzerError::ExpectedValue {
identifier: identifier.clone(), actual: statement.clone(),
}); });
} }
@ -124,7 +126,9 @@ impl<'a> Analyzer<'a> {
value, value,
} => todo!(), } => todo!(),
}, },
Statement::StructDefinition(_) => {} Statement::StructDefinition(_) => {
let StructDefinition { identifier, fields } = statement;
}
} }
Ok(()) Ok(())

View File

@ -332,12 +332,12 @@ impl Expression {
} }
Some(Type::Struct(StructType::Fields { Some(Type::Struct(StructType::Fields {
identifier: name.inner.clone(), name: name.inner.clone(),
fields: field_types, fields: field_types,
})) }))
} }
StructExpression::Unit { name } => Some(Type::Struct(StructType::Unit { StructExpression::Unit { name } => Some(Type::Struct(StructType::Unit {
identifier: name.inner.clone(), name: name.inner.clone(),
})), })),
}, },
Expression::TupleAccess(tuple_access_expression) => { Expression::TupleAccess(tuple_access_expression) => {

View File

@ -78,7 +78,7 @@ impl BuiltInFunction {
if let Some(value_arguments) = value_arguments { if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 { if value_arguments.len() == 1 {
if let Some(integer) = value_arguments[0].as_integer() { if let Some(integer) = value_arguments[0].as_integer() {
Ok(Some(Value::boolean(integer % 2 == 0))) Ok(Some(Value::Boolean(integer % 2 == 0)))
} else { } else {
Err(BuiltInFunctionError::ExpectedInteger) Err(BuiltInFunctionError::ExpectedInteger)
} }
@ -93,7 +93,7 @@ impl BuiltInFunction {
if let Some(value_arguments) = value_arguments { if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 { if value_arguments.len() == 1 {
if let Some(integer) = value_arguments[0].as_integer() { if let Some(integer) = value_arguments[0].as_integer() {
Ok(Some(Value::boolean(integer % 2 != 0))) Ok(Some(Value::Boolean(integer % 2 != 0)))
} else { } else {
Err(BuiltInFunctionError::ExpectedInteger) Err(BuiltInFunctionError::ExpectedInteger)
} }
@ -107,8 +107,8 @@ impl BuiltInFunction {
BuiltInFunction::Length => { BuiltInFunction::Length => {
if let Some(value_arguments) = value_arguments { if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 { if value_arguments.len() == 1 {
if let Some(list) = value_arguments[0].as_list() { if let Value::List(list) = &value_arguments[0] {
Ok(Some(Value::integer(list.len() as i64))) Ok(Some(Value::Integer(list.len() as i64)))
} else { } else {
Err(BuiltInFunctionError::ExpectedInteger) Err(BuiltInFunctionError::ExpectedInteger)
} }

View File

@ -332,14 +332,14 @@ impl Display for FunctionType {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum StructType { pub enum StructType {
Unit { Unit {
identifier: Identifier, name: Identifier,
}, },
Tuple { Tuple {
identifier: Identifier, name: Identifier,
fields: Vec<Type>, fields: Vec<Type>,
}, },
Fields { Fields {
identifier: Identifier, name: Identifier,
fields: Vec<(Identifier, Type)>, fields: Vec<(Identifier, Type)>,
}, },
} }
@ -362,7 +362,9 @@ impl Display for StructType {
write!(f, ")") write!(f, ")")
} }
StructType::Fields { StructType::Fields {
identifier, fields, .. name: identifier,
fields,
..
} => { } => {
write!(f, "{identifier} {{ ")?; write!(f, "{identifier} {{ ")?;

View File

@ -1,17 +1,15 @@
//! Dust value representation //! Dust value representation
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
collections::BTreeMap,
error::Error, error::Error,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
ops::{Range, RangeInclusive}, ops::{Range, RangeInclusive},
ptr, sync::{Arc, RwLock},
sync::{Arc, RwLock, RwLockWriteGuard},
}; };
use serde::{ use serde::{
de::{self, MapAccess, SeqAccess, Visitor}, de::{self, MapAccess, Visitor},
ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple}, ser::{SerializeStruct, SerializeStructVariant},
Deserialize, Deserializer, Serialize, Serializer, Deserialize, Deserializer, Serialize, Serializer,
}; };
@ -58,7 +56,7 @@ pub enum Value {
Character(char), Character(char),
Enum { name: Identifier, r#type: EnumType }, Enum { name: Identifier, r#type: EnumType },
Float(f64), Float(f64),
Function(Arc<Function>), Function(Function),
Integer(i64), Integer(i64),
List(Vec<Value>), List(Vec<Value>),
Mutable(Arc<RwLock<Value>>), Mutable(Arc<RwLock<Value>>),
@ -70,22 +68,93 @@ pub enum Value {
} }
impl Value { impl Value {
pub fn mutable(value: Value) -> Value {
Value::Mutable(Arc::new(RwLock::new(value)))
}
pub fn byte_range(start: u8, end: u8) -> Value { pub fn byte_range(start: u8, end: u8) -> Value {
Value::Range(Rangeable::Byte(start)..Rangeable::Byte(end)) Value::Range(Rangeable::Byte(start)..Rangeable::Byte(end))
} }
pub fn byte_range_inclusive(start: u8, end: u8) -> Value {
Value::RangeInclusive(Rangeable::Byte(start)..=Rangeable::Byte(end))
}
pub fn character_range(start: char, end: char) -> Value { pub fn character_range(start: char, end: char) -> Value {
Value::Range(Rangeable::Character(start)..Rangeable::Character(end)) Value::Range(Rangeable::Character(start)..Rangeable::Character(end))
} }
pub fn character_range_inclusive(start: char, end: char) -> Value {
Value::RangeInclusive(Rangeable::Character(start)..=Rangeable::Character(end))
}
pub fn float_range(start: f64, end: f64) -> Value { pub fn float_range(start: f64, end: f64) -> Value {
Value::Range(Rangeable::Float(start)..Rangeable::Float(end)) Value::Range(Rangeable::Float(start)..Rangeable::Float(end))
} }
pub fn float_range_inclusive(start: f64, end: f64) -> Value {
Value::RangeInclusive(Rangeable::Float(start)..=Rangeable::Float(end))
}
pub fn integer_range(start: i64, end: i64) -> Value { pub fn integer_range(start: i64, end: i64) -> Value {
Value::Range(Rangeable::Integer(start)..Rangeable::Integer(end)) Value::Range(Rangeable::Integer(start)..Rangeable::Integer(end))
} }
pub fn integer_range_inclusive(start: i64, end: i64) -> Value {
Value::RangeInclusive(Rangeable::Integer(start)..=Rangeable::Integer(end))
}
pub fn string<T: ToString>(to_string: T) -> Value {
Value::String(to_string.to_string())
}
pub fn as_boolean(&self) -> Option<bool> {
match self {
Value::Boolean(value) => Some(*value),
Value::Mutable(locked) => locked.read().unwrap().as_boolean(),
_ => None,
}
}
pub fn as_byte(&self) -> Option<u8> {
match self {
Value::Byte(value) => Some(*value),
Value::Mutable(locked) => locked.read().unwrap().as_byte(),
_ => None,
}
}
pub fn as_character(&self) -> Option<char> {
match self {
Value::Character(value) => Some(*value),
Value::Mutable(locked) => locked.read().unwrap().as_character(),
_ => None,
}
}
pub fn as_float(&self) -> Option<f64> {
match self {
Value::Float(value) => Some(*value),
Value::Mutable(locked) => locked.read().unwrap().as_float(),
_ => None,
}
}
pub fn as_integer(&self) -> Option<i64> {
match self {
Value::Integer(value) => Some(*value),
Value::Mutable(locked) => locked.read().unwrap().as_integer(),
_ => None,
}
}
pub fn as_mutable(&self) -> Result<&Arc<RwLock<Value>>, ValueError> {
match self {
Value::Mutable(inner) => Ok(inner),
_ => Err(ValueError::CannotMutate(self.clone())),
}
}
pub fn into_mutable(self) -> Value { pub fn into_mutable(self) -> Value {
match self { match self {
Value::Mutable(_) => self, Value::Mutable(_) => self,
@ -97,13 +166,6 @@ impl Value {
matches!(self, Value::Mutable(_)) matches!(self, Value::Mutable(_))
} }
pub fn as_mutable(&self) -> Result<&Arc<RwLock<Value>>, ValueError> {
match self {
Value::Mutable(inner) => Ok(inner),
_ => Err(ValueError::CannotMutate(self.clone())),
}
}
pub fn mutate(&self, other: Value) -> Result<(), ValueError> { pub fn mutate(&self, other: Value) -> Result<(), ValueError> {
match self { match self {
Value::Mutable(inner) => *inner.write().unwrap() = other, Value::Mutable(inner) => *inner.write().unwrap() = other,
@ -135,9 +197,9 @@ impl Value {
Value::RangeInclusive(_) => Type::Range, Value::RangeInclusive(_) => Type::Range,
Value::String(_) => Type::String, Value::String(_) => Type::String,
Value::Struct(r#struct) => match r#struct { Value::Struct(r#struct) => match r#struct {
Struct::Unit { r#type } => r#type.clone(), Struct::Unit { r#type } => Type::Struct(r#type.clone()),
Struct::Tuple { r#type, .. } => r#type.clone(), Struct::Tuple { r#type, .. } => Type::Struct(r#type.clone()),
Struct::Fields { r#type, .. } => r#type.clone(), Struct::Fields { r#type, .. } => Type::Struct(r#type.clone()),
}, },
Value::Tuple(values) => { Value::Tuple(values) => {
let item_types = values.iter().map(Value::r#type).collect(); let item_types = values.iter().map(Value::r#type).collect();
@ -149,16 +211,24 @@ impl Value {
pub fn get_field(&self, field: &Identifier) -> Option<Value> { pub fn get_field(&self, field: &Identifier) -> Option<Value> {
match self { match self {
Value::Struct(Struct::Fields { fields, .. }) => { Value::Mutable(inner) => inner.read().unwrap().get_field(field),
fields.iter().find_map(|(identifier, value)| { Value::Struct(Struct::Fields {
fields,
r#type:
StructType::Fields {
fields: field_types,
..
},
}) => field_types
.iter()
.zip(fields.iter())
.find_map(|((identifier, _), value)| {
if identifier == field { if identifier == field {
Some(value.clone()) Some(value.clone())
} else { } else {
None None
} }
}) }),
}
Value::Mutable(inner) => inner.clone().read().unwrap().get_field(field),
_ => None, _ => None,
} }
} }
@ -174,7 +244,9 @@ impl Value {
pub fn add(&self, other: &Value) -> Result<Value, ValueError> { pub fn add(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(Value::Float(left), Value::Float(right)) => Ok(Value::Float(left + right)), (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left + right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left + right)), (Value::Integer(left), Value::Integer(right)) => {
Ok(Value::Integer(left.saturating_add(*right)))
}
(Value::String(left), Value::String(right)) => { (Value::String(left), Value::String(right)) => {
Ok(Value::String(format!("{}{}", left, right))) Ok(Value::String(format!("{}{}", left, right)))
} }
@ -231,7 +303,9 @@ impl Value {
pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> { pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(Value::Float(left), Value::Float(right)) => Ok(Value::Float(left - right)), (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left - right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left - right)), (Value::Integer(left), Value::Integer(right)) => {
Ok(Value::Integer(left.saturating_sub(*right)))
}
(Value::Mutable(left), Value::Mutable(right)) => { (Value::Mutable(left), Value::Mutable(right)) => {
let left = left.read().unwrap(); let left = left.read().unwrap();
let right = right.read().unwrap(); let right = right.read().unwrap();
@ -277,7 +351,9 @@ impl Value {
pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> { pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self, other) {
(Value::Float(left), Value::Float(right)) => Ok(Value::Float(left * right)), (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left * right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left * right)), (Value::Integer(left), Value::Integer(right)) => {
Ok(Value::Integer(left.saturating_mul(*right)))
}
(Value::Mutable(left), Value::Mutable(right)) => { (Value::Mutable(left), Value::Mutable(right)) => {
let left = left.read().unwrap(); let left = left.read().unwrap();
let right = right.read().unwrap(); let right = right.read().unwrap();
@ -324,7 +400,7 @@ impl Value {
match (self, other) { match (self, other) {
(Value::Float(left), Value::Float(right)) => Ok(Value::Float(left / right)), (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left / right)),
(Value::Integer(left), Value::Integer(right)) => { (Value::Integer(left), Value::Integer(right)) => {
Ok(Value::Float((*left as f64) / (*right as f64))) Ok(Value::Integer(left.saturating_div(*right)))
} }
(Value::Mutable(left), Value::Mutable(right)) => { (Value::Mutable(left), Value::Mutable(right)) => {
let left = left.read().unwrap(); let left = left.read().unwrap();
@ -472,12 +548,28 @@ impl Value {
match (self, other) { match (self, other) {
(Value::Float(left), Value::Float(right)) => Ok(Value::Boolean(left < right)), (Value::Float(left), Value::Float(right)) => Ok(Value::Boolean(left < right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Boolean(left < right)), (Value::Integer(left), Value::Integer(right)) => Ok(Value::Boolean(left < right)),
(Value::Float(left), Value::Integer(right)) => {
Ok(Value::Boolean(*left < *right as f64))
}
(Value::Integer(left), Value::Float(right)) => {
Ok(Value::Boolean((*left as f64) < *right))
}
(Value::Mutable(left), Value::Mutable(right)) => { (Value::Mutable(left), Value::Mutable(right)) => {
let left = left.read().unwrap(); let left = left.read().unwrap();
let right = right.read().unwrap(); let right = right.read().unwrap();
left.less_than(&right) left.less_than(&right)
} }
(Value::Mutable(left), right) => {
let left = left.read().unwrap();
left.less_than(right)
}
(left, Value::Mutable(right)) => {
let right = right.read().unwrap();
left.less_than(&right)
}
_ => Err(ValueError::CannotLessThan(self.clone(), other.clone())), _ => Err(ValueError::CannotLessThan(self.clone(), other.clone())),
} }
} }
@ -486,12 +578,28 @@ impl Value {
match (self, other) { match (self, other) {
(Value::Float(left), Value::Float(right)) => Ok(Value::Boolean(left <= right)), (Value::Float(left), Value::Float(right)) => Ok(Value::Boolean(left <= right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Boolean(left <= right)), (Value::Integer(left), Value::Integer(right)) => Ok(Value::Boolean(left <= right)),
(Value::Float(left), Value::Integer(right)) => {
Ok(Value::Boolean(*left <= *right as f64))
}
(Value::Integer(left), Value::Float(right)) => {
Ok(Value::Boolean(*left as f64 <= *right))
}
(Value::Mutable(left), Value::Mutable(right)) => { (Value::Mutable(left), Value::Mutable(right)) => {
let left = left.read().unwrap(); let left = left.read().unwrap();
let right = right.read().unwrap(); let right = right.read().unwrap();
left.less_than_or_equal(&right) left.less_than_or_equal(&right)
} }
(Value::Mutable(left), right) => {
let left = left.read().unwrap();
left.less_than_or_equal(right)
}
(left, Value::Mutable(right)) => {
let right = right.read().unwrap();
left.less_than_or_equal(&right)
}
_ => Err(ValueError::CannotLessThanOrEqual( _ => Err(ValueError::CannotLessThanOrEqual(
self.clone(), self.clone(),
other.clone(), other.clone(),
@ -503,12 +611,28 @@ impl Value {
match (self, other) { match (self, other) {
(Value::Float(left), Value::Float(right)) => Ok(Value::Boolean(left > right)), (Value::Float(left), Value::Float(right)) => Ok(Value::Boolean(left > right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Boolean(left > right)), (Value::Integer(left), Value::Integer(right)) => Ok(Value::Boolean(left > right)),
(Value::Float(left), Value::Integer(right)) => {
Ok(Value::Boolean(*left > *right as f64))
}
(Value::Integer(left), Value::Float(right)) => {
Ok(Value::Boolean(*left as f64 > *right))
}
(Value::Mutable(left), Value::Mutable(right)) => { (Value::Mutable(left), Value::Mutable(right)) => {
let left = left.read().unwrap(); let left = left.read().unwrap();
let right = right.read().unwrap(); let right = right.read().unwrap();
left.greater_than(&right) left.greater_than(&right)
} }
(Value::Mutable(left), right) => {
let left = left.read().unwrap();
left.greater_than(right)
}
(left, Value::Mutable(right)) => {
let right = right.read().unwrap();
left.greater_than(&right)
}
_ => Err(ValueError::CannotGreaterThan(self.clone(), other.clone())), _ => Err(ValueError::CannotGreaterThan(self.clone(), other.clone())),
} }
} }
@ -517,12 +641,28 @@ impl Value {
match (self, other) { match (self, other) {
(Value::Float(left), Value::Float(right)) => Ok(Value::Boolean(left >= right)), (Value::Float(left), Value::Float(right)) => Ok(Value::Boolean(left >= right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Boolean(left >= right)), (Value::Integer(left), Value::Integer(right)) => Ok(Value::Boolean(left >= right)),
(Value::Float(left), Value::Integer(right)) => {
Ok(Value::Boolean(*left >= *right as f64))
}
(Value::Integer(left), Value::Float(right)) => {
Ok(Value::Boolean(*left as f64 >= *right))
}
(Value::Mutable(left), Value::Mutable(right)) => { (Value::Mutable(left), Value::Mutable(right)) => {
let left = left.read().unwrap(); let left = left.read().unwrap();
let right = right.read().unwrap(); let right = right.read().unwrap();
left.greater_than_or_equal(&right) left.greater_than_or_equal(&right)
} }
(Value::Mutable(left), right) => {
let left = left.read().unwrap();
left.greater_than_or_equal(right)
}
(left, Value::Mutable(right)) => {
let right = right.read().unwrap();
left.greater_than_or_equal(&right)
}
_ => Err(ValueError::CannotGreaterThanOrEqual( _ => Err(ValueError::CannotGreaterThanOrEqual(
self.clone(), self.clone(),
other.clone(), other.clone(),
@ -531,15 +671,15 @@ impl Value {
} }
pub fn and(&self, other: &Value) -> Result<Value, ValueError> { pub fn and(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self.as_boolean(), other.as_boolean()) {
(Value::Boolean(left), Value::Boolean(right)) => Ok(Value::Boolean(*left && *right)), (Some(left), Some(right)) => Ok(Value::Boolean(left && right)),
_ => Err(ValueError::CannotAnd(self.clone(), other.clone())), _ => Err(ValueError::CannotAnd(self.clone(), other.clone())),
} }
} }
pub fn or(&self, other: &Value) -> Result<Value, ValueError> { pub fn or(&self, other: &Value) -> Result<Value, ValueError> {
match (self, other) { match (self.as_boolean(), other.as_boolean()) {
(Value::Boolean(left), Value::Boolean(right)) => Ok(Value::Boolean(*left || *right)), (Some(left), Some(right)) => Ok(Value::Boolean(left || right)),
_ => Err(ValueError::CannotOr(self.clone(), other.clone())), _ => Err(ValueError::CannotOr(self.clone(), other.clone())),
} }
} }
@ -918,15 +1058,15 @@ impl<'de> Deserialize<'de> for Function {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Struct { pub enum Struct {
Unit { Unit {
r#type: Type, r#type: StructType,
}, },
Tuple { Tuple {
r#type: Type, r#type: StructType,
fields: Vec<Value>, fields: Vec<Value>,
}, },
Fields { Fields {
r#type: Type, r#type: StructType,
fields: Vec<(Identifier, Value)>, fields: Vec<Value>,
}, },
} }
@ -947,24 +1087,34 @@ impl Display for Struct {
write!(f, ")") write!(f, ")")
} }
Struct::Fields { fields, .. } => { Struct::Fields {
fields,
r#type:
StructType::Fields {
fields: field_types,
..
},
} => {
write!(f, "{{ ")?; write!(f, "{{ ")?;
for (index, (identifier, r#type)) in fields.iter().enumerate() { for (index, ((identifier, _), value)) in
field_types.iter().zip(fields.iter()).enumerate()
{
if index > 0 { if index > 0 {
write!(f, ", ")?; write!(f, ", ")?;
} }
write!(f, "{}: {}", identifier, r#type)?; write!(f, "{}: {}", identifier, value)?;
} }
write!(f, " }}") write!(f, " }}")
} }
_ => Ok(()),
} }
} }
} }
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
enum Rangeable { enum Rangeable {
Byte(u8), Byte(u8),
Character(char), Character(char),
@ -985,6 +1135,12 @@ impl Display for Rangeable {
impl Eq for Rangeable {} impl Eq for Rangeable {}
impl PartialOrd for Rangeable {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Rangeable { impl Ord for Rangeable {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
match (self, other) { match (self, other) {

View File

@ -16,10 +16,10 @@ use crate::{
AbstractSyntaxTree, BlockExpression, CallExpression, ComparisonOperator, ElseExpression, AbstractSyntaxTree, BlockExpression, CallExpression, ComparisonOperator, ElseExpression,
FieldAccessExpression, IfExpression, LetStatement, ListExpression, ListIndexExpression, FieldAccessExpression, IfExpression, LetStatement, ListExpression, ListIndexExpression,
LiteralExpression, LogicOperator, LoopExpression, MathOperator, Node, OperatorExpression, LiteralExpression, LogicOperator, LoopExpression, MathOperator, Node, OperatorExpression,
RangeExpression, Statement, RangeExpression, Statement, StructDefinition,
}, },
parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError, parse, Analyzer, BuiltInFunctionError, Context, DustError, Expression, Identifier, ParseError,
Span, Value, ValueError, Span, StructType, Type, Value, ValueError,
}; };
/// Run the source code and return the result. /// Run the source code and return the result.
@ -30,7 +30,7 @@ use crate::{
/// # use dust_lang::value::Value; /// # use dust_lang::value::Value;
/// let result = run("40 + 2"); /// let result = run("40 + 2");
/// ///
/// assert_eq!(result, Ok(Some(Value::integer(42)))); /// assert_eq!(result, Ok(Some(Value::Integer(42))));
/// ``` /// ```
pub fn run(source: &str) -> Result<Option<Value>, DustError> { pub fn run(source: &str) -> Result<Option<Value>, DustError> {
let context = Context::new(); let context = Context::new();
@ -45,12 +45,12 @@ pub fn run(source: &str) -> Result<Option<Value>, DustError> {
/// # use dust_lang::{Context, Identifier, Value, run_with_context}; /// # use dust_lang::{Context, Identifier, Value, run_with_context};
/// let context = Context::new(); /// let context = Context::new();
/// ///
/// context.set_value(Identifier::new("foo"), Value::integer(40)); /// context.set_value(Identifier::new("foo"), Value::Integer(40));
/// context.update_last_position(&Identifier::new("foo"), (100, 100)); /// context.update_last_position(&Identifier::new("foo"), (100, 100));
/// ///
/// let result = run_with_context("foo + 2", context); /// let result = run_with_context("foo + 2", context);
/// ///
/// assert_eq!(result, Ok(Some(Value::integer(42)))); /// assert_eq!(result, Ok(Some(Value::Integer(42))));
/// ``` /// ```
pub fn run_with_context(source: &str, context: Context) -> Result<Option<Value>, DustError> { pub fn run_with_context(source: &str, context: Context) -> Result<Option<Value>, DustError> {
let abstract_syntax_tree = parse(source)?; let abstract_syntax_tree = parse(source)?;
@ -119,7 +119,20 @@ impl Vm {
Ok(None) Ok(None)
} }
Statement::StructDefinition(_) => todo!(), Statement::StructDefinition(struct_definition) => {
let (name, struct_type) = match struct_definition.inner {
StructDefinition::Unit { name } => {
(name.inner.clone(), StructType::Unit { name: name.inner })
}
StructDefinition::Tuple { name, items } => todo!(),
StructDefinition::Fields { name, fields } => todo!(),
};
self.context
.set_type(name, Type::Struct(struct_type), struct_definition.position);
Ok(None)
}
}; };
if collect_garbage { if collect_garbage {
@ -203,20 +216,65 @@ impl Vm {
Expression::Operator(operator_expression) => { Expression::Operator(operator_expression) => {
self.run_operator(*operator_expression.inner, collect_garbage) self.run_operator(*operator_expression.inner, collect_garbage)
} }
Expression::Range(range_expression) => match range_expression.inner.as_ref() { Expression::Range(range_expression) => match *range_expression.inner {
RangeExpression::Exclusive { start, end } => { RangeExpression::Exclusive { start, end } => {
let start_position = start.position(); let start_position = start.position();
let start = self let start = self
.run_expression(*start.inner, collect_garbage)? .run_expression(start, collect_garbage)?
.expect_value(start_position)?; .expect_value(start_position)?;
let end_position = end.position(); let end_position = end.position();
let end = self let end = self
.run_expression(*end.inner, collect_garbage)? .run_expression(end, collect_garbage)?
.expect_value(end_position)?; .expect_value(end_position)?;
Ok(Evaluation::Return(Some(Value::range(start..end)))) match (start, end) {
(Value::Byte(start), Value::Byte(end)) => {
Ok(Evaluation::Return(Some(Value::byte_range(start, end))))
}
(Value::Character(start), Value::Character(end)) => {
Ok(Evaluation::Return(Some(Value::character_range(start, end))))
}
(Value::Float(start), Value::Float(end)) => {
Ok(Evaluation::Return(Some(Value::float_range(start, end))))
}
(Value::Integer(start), Value::Integer(end)) => {
Ok(Evaluation::Return(Some(Value::integer_range(start, end))))
}
_ => Err(VmError::InvalidRange {
start_position,
end_position,
}),
}
}
RangeExpression::Inclusive { start, end } => {
let start_position = start.position();
let start = self
.run_expression(start, collect_garbage)?
.expect_value(start_position)?;
let end_position = end.position();
let end = self
.run_expression(end, collect_garbage)?
.expect_value(end_position)?;
match (start, end) {
(Value::Byte(start), Value::Byte(end)) => Ok(Evaluation::Return(Some(
Value::byte_range_inclusive(start, end),
))),
(Value::Character(start), Value::Character(end)) => Ok(Evaluation::Return(
Some(Value::character_range_inclusive(start, end)),
)),
(Value::Float(start), Value::Float(end)) => Ok(Evaluation::Return(Some(
Value::float_range_inclusive(start, end),
))),
(Value::Integer(start), Value::Integer(end)) => Ok(Evaluation::Return(
Some(Value::integer_range_inclusive(start, end)),
)),
_ => Err(VmError::InvalidRange {
start_position,
end_position,
}),
}
} }
RangeExpression::Inclusive { start, end } => todo!(),
}, },
Expression::Struct(_) => todo!(), Expression::Struct(_) => todo!(),
Expression::TupleAccess(_) => todo!(), Expression::TupleAccess(_) => todo!(),
@ -341,7 +399,7 @@ impl Vm {
let integer = value let integer = value
.as_integer() .as_integer()
.ok_or(VmError::ExpectedBoolean { position })?; .ok_or(VmError::ExpectedBoolean { position })?;
let negated = Value::integer(-integer); let negated = Value::Integer(-integer);
Ok(Evaluation::Return(Some(negated))) Ok(Evaluation::Return(Some(negated)))
} }
@ -353,7 +411,7 @@ impl Vm {
let boolean = value let boolean = value
.as_boolean() .as_boolean()
.ok_or(VmError::ExpectedBoolean { position })?; .ok_or(VmError::ExpectedBoolean { position })?;
let not = Value::boolean(!boolean); let not = Value::Boolean(!boolean);
Ok(Evaluation::Return(Some(not))) Ok(Evaluation::Return(Some(not)))
} }
@ -442,11 +500,10 @@ impl Vm {
fn run_literal(&self, literal: LiteralExpression) -> Result<Evaluation, VmError> { fn run_literal(&self, literal: LiteralExpression) -> Result<Evaluation, VmError> {
let value = match literal { let value = match literal {
LiteralExpression::Boolean(boolean) => Value::boolean(boolean), LiteralExpression::Boolean(boolean) => Value::Boolean(boolean),
LiteralExpression::Float(float) => Value::float(float), LiteralExpression::Float(float) => Value::Float(float),
LiteralExpression::Integer(integer) => Value::integer(integer), LiteralExpression::Integer(integer) => Value::Integer(integer),
LiteralExpression::String(string) => Value::string(string), LiteralExpression::String(string) => Value::String(string),
LiteralExpression::Value(value) => value,
}; };
Ok(Evaluation::Return(Some(value))) Ok(Evaluation::Return(Some(value)))
@ -499,7 +556,7 @@ impl Vm {
}); });
}; };
let function = if let Some(function) = invoker_value.as_function() { let function = if let Value::Function(function) = invoker_value {
function function
} else { } else {
return Err(VmError::ExpectedFunction { return Err(VmError::ExpectedFunction {
@ -569,7 +626,7 @@ impl Vm {
.run_expression(repeat_operand, collect_garbage)? .run_expression(repeat_operand, collect_garbage)?
.expect_value(position)?; .expect_value(position)?;
Ok(Evaluation::Return(Some(Value::list(vec![ Ok(Evaluation::Return(Some(Value::List(vec![
value; value;
length as usize length as usize
])))) ]))))
@ -586,7 +643,7 @@ impl Vm {
values.push(value); values.push(value);
} }
Ok(Evaluation::Return(Some(Value::list(values)))) Ok(Evaluation::Return(Some(Value::List(values))))
} }
} }
} }
@ -769,6 +826,10 @@ pub enum VmError {
ExpectedValue { ExpectedValue {
position: Span, position: Span,
}, },
InvalidRange {
start_position: Span,
end_position: Span,
},
UndefinedVariable { UndefinedVariable {
identifier: Identifier, identifier: Identifier,
position: Span, position: Span,
@ -803,6 +864,11 @@ impl VmError {
Self::ExpectedFunction { position, .. } => *position, Self::ExpectedFunction { position, .. } => *position,
Self::ExpectedList { position } => *position, Self::ExpectedList { position } => *position,
Self::ExpectedValue { position } => *position, Self::ExpectedValue { position } => *position,
Self::InvalidRange {
start_position,
end_position,
..
} => (start_position.0, end_position.1),
Self::UndefinedVariable { position, .. } => *position, Self::UndefinedVariable { position, .. } => *position,
Self::UndefinedProperty { Self::UndefinedProperty {
property_position, .. property_position, ..
@ -891,6 +957,16 @@ impl Display for VmError {
Self::ExpectedValue { position } => { Self::ExpectedValue { position } => {
write!(f, "Expected a value at position: {:?}", position) write!(f, "Expected a value at position: {:?}", position)
} }
Self::InvalidRange {
start_position,
end_position,
} => {
write!(
f,
"Invalid range with start position: {:?} and end position: {:?}",
start_position, end_position
)
}
Self::UndefinedVariable { Self::UndefinedVariable {
identifier, identifier,
position, position,
@ -912,7 +988,7 @@ impl Display for VmError {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::Struct; use crate::{Struct, StructType, Type};
use super::*; use super::*;
@ -920,7 +996,7 @@ mod tests {
fn async_block() { fn async_block() {
let input = "let mut x = 1; async { x += 1; x -= 1; } x"; let input = "let mut x = 1; async { x += 1; x -= 1; } x";
assert!(run(input).unwrap().unwrap().as_integer().is_some()); assert_eq!(run(input), Ok(Some(Value::Integer(1))));
} }
#[test] #[test]
@ -929,12 +1005,15 @@ mod tests {
assert_eq!( assert_eq!(
run(input), run(input),
Ok(Some(Value::r#struct(Struct::Fields { Ok(Some(Value::Struct(Struct::Fields {
name: Identifier::new("Foo"), r#type: StructType::Fields {
fields: vec![ name: Identifier::new("Foo"),
(Identifier::new("bar"), Value::integer(42)), fields: vec![
(Identifier::new("baz"), Value::float(4.0)) (Identifier::new("bar"), Type::Integer),
] (Identifier::new("baz"), Type::Float)
]
},
fields: vec![Value::Integer(42), Value::Float(4.0)]
}))) })))
); );
} }
@ -949,9 +1028,12 @@ mod tests {
assert_eq!( assert_eq!(
run(input), run(input),
Ok(Some(Value::r#struct(Struct::Tuple { Ok(Some(Value::Struct(Struct::Tuple {
name: Identifier::new("Foo"), r#type: StructType::Tuple {
fields: vec![Value::integer(42)] name: Identifier::new("Foo"),
fields: vec![Type::Integer]
},
fields: vec![Value::Integer(42)]
}))) })))
) )
} }
@ -962,9 +1044,11 @@ mod tests {
assert_eq!( assert_eq!(
run(input), run(input),
Ok(Some(Value::r#struct(Struct::Tuple { Ok(Some(Value::Struct(Struct::Tuple {
name: Identifier::new("Foo"), r#type: StructType::Unit {
fields: vec![Value::integer(42)] name: Identifier::new("Foo")
},
fields: vec![Value::Integer(42)]
}))) })))
); );
} }
@ -979,8 +1063,10 @@ mod tests {
assert_eq!( assert_eq!(
run(input), run(input),
Ok(Some(Value::r#struct(Struct::Unit { Ok(Some(Value::Struct(Struct::Unit {
name: Identifier::new("Foo") r#type: StructType::Unit {
name: Identifier::new("Foo")
}
}))) })))
) )
} }
@ -991,8 +1077,10 @@ mod tests {
assert_eq!( assert_eq!(
run(input), run(input),
Ok(Some(Value::r#struct(Struct::Unit { Ok(Some(Value::Struct(Struct::Unit {
name: Identifier::new("Foo") r#type: StructType::Unit {
name: Identifier::new("Foo")
}
}))) })))
); );
} }
@ -1001,7 +1089,7 @@ mod tests {
fn list_index_nested() { fn list_index_nested() {
let input = "[[1, 2], [42, 4], [5, 6]][1][0]"; 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] #[test]
@ -1010,9 +1098,9 @@ mod tests {
assert_eq!( assert_eq!(
run(input), run(input),
Ok(Some(Value::list(vec![ Ok(Some(Value::List(vec![
Value::integer(2), Value::Integer(2),
Value::integer(3) Value::Integer(3)
]))) ])))
); );
} }
@ -1021,35 +1109,35 @@ mod tests {
fn range() { fn range() {
let input = "1..5"; let input = "1..5";
assert_eq!(run(input), Ok(Some(Value::range(1..5)))); assert_eq!(run(input), Ok(Some(Value::integer_range(1, 5))));
} }
#[test] #[test]
fn negate_expression() { fn negate_expression() {
let input = "let x = -42; -x"; 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] #[test]
fn not_expression() { fn not_expression() {
let input = "!(1 == 2 || 3 == 4 || 5 == 6)"; 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] #[test]
fn list_index() { fn list_index() {
let input = "[1, 42, 3][1]"; 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] #[test]
fn map_property_access() { fn map_property_access() {
let input = "{ a = 42 }.a"; let input = "{ a = 42 }.a";
assert_eq!(run(input), Ok(Some(Value::integer(42)))); assert_eq!(run(input), Ok(Some(Value::Integer(42))));
} }
#[test] #[test]
@ -1063,7 +1151,7 @@ mod tests {
fn to_string() { fn to_string() {
let input = "to_string(42)"; let input = "to_string(42)";
assert_eq!(run(input), Ok(Some(Value::string("42".to_string())))); assert_eq!(run(input), Ok(Some(Value::string("42"))));
} }
#[test] #[test]
@ -1077,7 +1165,7 @@ mod tests {
fn if_else() { fn if_else() {
let input = "if false { 1 } else { 2 }"; let input = "if false { 1 } else { 2 }";
assert_eq!(run(input), Ok(Some(Value::integer(2)))); assert_eq!(run(input), Ok(Some(Value::Integer(2))));
} }
#[test] #[test]
@ -1091,155 +1179,153 @@ mod tests {
fn if_else_if_else() { fn if_else_if_else() {
let input = "if false { 1 } else if false { 2 } else { 3 }"; 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] #[test]
fn while_loop() { fn while_loop() {
let input = "let mut x = 0; while x < 5 { x += 1; } x"; let input = "let mut x = 0; while x < 5 { x += 1; } x";
assert_eq!(run(input), Ok(Some(Value::integer(5)))); assert_eq!(run(input), Ok(Some(Value::Integer(5))));
} }
#[test] #[test]
fn subtract_assign() { fn subtract_assign() {
let input = "let mut x = 1; x -= 1; x"; let input = "let mut x = 1; x -= 1; x";
assert_eq!(run(input), Ok(Some(Value::integer(0)))); assert_eq!(run(input), Ok(Some(Value::mutable(Value::Integer(0)))));
} }
#[test] #[test]
fn add_assign() { fn add_assign() {
env_logger::builder().is_test(true).try_init().ok();
let input = "let mut x = 1; x += 1; x"; let input = "let mut x = 1; x += 1; x";
assert_eq!(run(input), Ok(Some(Value::integer(2)))); assert_eq!(run(input), Ok(Some(Value::mutable(Value::Integer(2)))));
} }
#[test] #[test]
fn and() { fn and() {
let input = "true && true"; let input = "true && true";
assert_eq!(run(input), Ok(Some(Value::boolean(true)))); assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
} }
#[test] #[test]
fn or() { fn or() {
let input = "true || false"; let input = "true || false";
assert_eq!(run(input), Ok(Some(Value::boolean(true)))); assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
} }
#[test] #[test]
fn integer_equal() { fn integer_equal() {
let input = "42 == 42"; let input = "42 == 42";
assert_eq!(run(input), Ok(Some(Value::boolean(true)))); assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
} }
#[test] #[test]
fn modulo() { fn modulo() {
let input = "42 % 2"; let input = "42 % 2";
assert_eq!(run(input), Ok(Some(Value::integer(0)))); assert_eq!(run(input), Ok(Some(Value::Integer(0))));
} }
#[test] #[test]
fn divide() { fn divide() {
let input = "42 / 2"; let input = "42 / 2";
assert_eq!(run(input), Ok(Some(Value::integer(21)))); assert_eq!(run(input), Ok(Some(Value::Integer(21))));
} }
#[test] #[test]
fn less_than() { fn less_than() {
let input = "2 < 3"; let input = "2 < 3";
assert_eq!(run(input), Ok(Some(Value::boolean(true)))); assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
} }
#[test] #[test]
fn less_than_or_equal() { fn less_than_or_equal() {
let input = "42 <= 42"; let input = "42 <= 42";
assert_eq!(run(input), Ok(Some(Value::boolean(true)))); assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
} }
#[test] #[test]
fn greater_than() { fn greater_than() {
let input = "2 > 3"; let input = "2 > 3";
assert_eq!(run(input), Ok(Some(Value::boolean(false)))); assert_eq!(run(input), Ok(Some(Value::Boolean(false))));
} }
#[test] #[test]
fn greater_than_or_equal() { fn greater_than_or_equal() {
let input = "42 >= 42"; let input = "42 >= 42";
assert_eq!(run(input), Ok(Some(Value::boolean(true)))); assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
} }
#[test] #[test]
fn integer_saturating_add() { fn integer_saturating_add() {
let input = "9223372036854775807 + 1"; 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] #[test]
fn integer_saturating_sub() { fn integer_saturating_sub() {
let input = "-9223372036854775808 - 1"; 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] #[test]
fn multiply() { fn multiply() {
let input = "2 * 3"; let input = "2 * 3";
assert_eq!(run(input), Ok(Some(Value::integer(6)))); assert_eq!(run(input), Ok(Some(Value::Integer(6))));
} }
#[test] #[test]
fn boolean() { fn boolean() {
let input = "true"; let input = "true";
assert_eq!(run(input), Ok(Some(Value::boolean(true)))); assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
} }
#[test] #[test]
fn is_even() { fn is_even() {
let input = "is_even(42)"; let input = "is_even(42)";
assert_eq!(run(input), Ok(Some(Value::boolean(true)))); assert_eq!(run(input), Ok(Some(Value::Boolean(true))));
} }
#[test] #[test]
fn is_odd() { fn is_odd() {
let input = "is_odd(42)"; let input = "is_odd(42)";
assert_eq!(run(input), Ok(Some(Value::boolean(false)))); assert_eq!(run(input), Ok(Some(Value::Boolean(false))));
} }
#[test] #[test]
fn length() { fn length() {
let input = "length([1, 2, 3])"; let input = "length([1, 2, 3])";
assert_eq!(run(input), Ok(Some(Value::integer(3)))); assert_eq!(run(input), Ok(Some(Value::Integer(3))));
} }
#[test] #[test]
fn add() { fn add() {
let input = "1 + 2"; let input = "1 + 2";
assert_eq!(run(input), Ok(Some(Value::integer(3)))); assert_eq!(run(input), Ok(Some(Value::Integer(3))));
} }
#[test] #[test]
fn add_multiple() { fn add_multiple() {
let input = "1 + 2 + 3"; let input = "1 + 2 + 3";
assert_eq!(run(input), Ok(Some(Value::integer(6)))); assert_eq!(run(input), Ok(Some(Value::Integer(6))));
} }
} }