From c0ab5a84a28166b5dd931513b5ba8c723c9e9d52 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 20 Aug 2024 04:12:43 -0400 Subject: [PATCH] Pass VM tests --- dust-lang/src/analyzer.rs | 4 -- dust-lang/src/ast/expression.rs | 25 ++------ dust-lang/src/vm.rs | 106 +++++++++++--------------------- 3 files changed, 42 insertions(+), 93 deletions(-) diff --git a/dust-lang/src/analyzer.rs b/dust-lang/src/analyzer.rs index bc46a36..5eea8db 100644 --- a/dust-lang/src/analyzer.rs +++ b/dust-lang/src/analyzer.rs @@ -289,10 +289,6 @@ impl<'a> Analyzer<'a> { } }, Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { - StructExpression::Unit { name } => { - self.context - .update_last_position(&name.inner, name.position); - } StructExpression::Fields { name, fields } => { self.context .update_last_position(&name.inner, name.position); diff --git a/dust-lang/src/ast/expression.rs b/dust-lang/src/ast/expression.rs index f73a0a1..1d02c8e 100644 --- a/dust-lang/src/ast/expression.rs +++ b/dust-lang/src/ast/expression.rs @@ -407,9 +407,6 @@ impl Expression { fields: types, })) } - StructExpression::Unit { name } => Some(Type::Struct(StructType::Unit { - name: name.inner.clone(), - })), }, Expression::TupleAccess(tuple_access_expression) => { let TupleAccessExpression { tuple, index } = tuple_access_expression.inner.as_ref(); @@ -647,15 +644,6 @@ impl Ord for PrimitiveValueExpression { } } -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -pub struct RawStringExpression(pub String); - -impl Display for RawStringExpression { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } -} - impl From for LiteralExpression { fn from(value: i64) -> Self { LiteralExpression::Primitive(PrimitiveValueExpression::Integer(value)) @@ -664,13 +652,13 @@ impl From for LiteralExpression { impl From for LiteralExpression { fn from(value: String) -> Self { - LiteralExpression::String(RawStringExpression(value)) + LiteralExpression::String(value) } } impl From<&str> for LiteralExpression { fn from(value: &str) -> Self { - LiteralExpression::String(RawStringExpression(value.to_string())) + LiteralExpression::String(value.to_string()) } } @@ -695,7 +683,7 @@ impl From for LiteralExpression { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum LiteralExpression { Primitive(PrimitiveValueExpression), - String(RawStringExpression), + String(String), } impl Display for LiteralExpression { @@ -1022,10 +1010,8 @@ impl Display for LoopExpression { #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub enum StructExpression { - // The tuple struct expression is omitted because it is redundant with call expression - Unit { - name: Node, - }, + // The unit struct is omitted because it is redundant with a plain identifier + // The tuple struct is omitted because it is redundant with the call expression Fields { name: Node, fields: Vec<(Node, Expression)>, @@ -1035,7 +1021,6 @@ pub enum StructExpression { impl Display for StructExpression { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { - StructExpression::Unit { name } => write!(f, "{}", name), StructExpression::Fields { name, fields } => { write!(f, "{} {{", name)?; diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 99899e0..d65a2ee 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -17,9 +17,10 @@ use crate::{ AbstractSyntaxTree, BlockExpression, CallExpression, ComparisonOperator, ElseExpression, FieldAccessExpression, IfExpression, LetStatement, ListExpression, ListIndexExpression, LiteralExpression, LogicOperator, LoopExpression, MapExpression, MathOperator, Node, - OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span, - Statement, StructDefinition, StructExpression, + OperatorExpression, PrimitiveValueExpression, RangeExpression, Span, Statement, + StructDefinition, StructExpression, }, + constructor::FieldsConstructor, parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, DustError, Expression, Identifier, ParseError, Struct, StructType, Type, Value, ValueError, }; @@ -281,67 +282,32 @@ impl Vm { ) -> Result { log::debug!("Running struct expression: {struct_expression}"); - match struct_expression { - StructExpression::Unit { name } => { - let position = name.position; - let r#type = self.context.get_type(&name.inner).ok_or_else(|| { - RuntimeError::UndefinedType { - identifier: name.inner.clone(), - position, - } - })?; + let StructExpression::Fields { name, fields } = struct_expression; - if let Type::Struct(StructType::Unit { name }) = r#type { - Ok(Evaluation::Return(Some(Value::Struct(Struct::Unit { - name, - })))) - } else { - Err(RuntimeError::ExpectedType { - expected: Type::Struct(StructType::Unit { name: name.inner }), - actual: r#type, - position, - }) - } - } - StructExpression::Fields { - name, - fields: expressions, - } => { - let position = name.position; - let r#type = self.context.get_type(&name.inner).ok_or_else(|| { - RuntimeError::UndefinedType { - identifier: name.inner.clone(), - position, - } - })?; - - if let Type::Struct(StructType::Fields { name, .. }) = r#type { - let mut values = HashMap::with_capacity(expressions.len()); - - for (identifier, expression) in expressions { - let expression_position = expression.position(); - let value = self - .run_expression(expression, collect_garbage)? - .expect_value(expression_position)?; - - values.insert(identifier.inner, value); - } - - Ok(Evaluation::Return(Some(Value::Struct(Struct::Fields { - name, - fields: values, - })))) - } else { - Err(RuntimeError::ExpectedType { - expected: Type::Struct(StructType::Fields { - name: name.inner, - fields: Default::default(), - }), - actual: r#type, - position, - }) + let position = name.position; + let constructor = self.context.get_constructor(&name.inner); + + if let Some(constructor) = constructor { + if let Constructor::Fields(fields_constructor) = constructor { + let mut arguments = HashMap::with_capacity(fields.len()); + + for (identifier, expression) in fields { + let position = expression.position(); + let value = self + .run_expression(expression, collect_garbage)? + .expect_value(position)?; + + arguments.insert(identifier.inner, value); } + + Ok(Evaluation::Return(Some( + fields_constructor.construct(arguments), + ))) + } else { + Err(RuntimeError::ExpectedFieldsConstructor { position }) } + } else { + Err(RuntimeError::ExpectedConstructor { position }) } } @@ -643,7 +609,7 @@ impl Vm { fn run_literal(&self, literal: LiteralExpression) -> Result { let value = match literal { - LiteralExpression::String(RawStringExpression(string)) => Value::String(string), + LiteralExpression::String(string) => Value::String(string), LiteralExpression::Primitive(primitive_expression) => match primitive_expression { PrimitiveValueExpression::Boolean(boolean) => Value::Boolean(boolean), PrimitiveValueExpression::Character(character) => Value::Character(character), @@ -978,7 +944,9 @@ pub enum RuntimeError { position: Span, }, ExpectedConstructor { - actual: Type, + position: Span, + }, + ExpectedFieldsConstructor { position: Span, }, ExpectedIdentifier { @@ -1052,6 +1020,7 @@ impl RuntimeError { Self::EnumVariantNotFound { position, .. } => *position, Self::ExpectedBoolean { position } => *position, Self::ExpectedConstructor { position, .. } => *position, + Self::ExpectedFieldsConstructor { position } => *position, Self::ExpectedFunction { position, .. } => *position, Self::ExpectedIdentifier { position } => *position, Self::ExpectedIdentifierOrString { position } => *position, @@ -1128,11 +1097,14 @@ impl Display for RuntimeError { Self::ExpectedBoolean { position } => { write!(f, "Expected a boolean at position: {:?}", position) } - Self::ExpectedConstructor { actual, position } => { + Self::ExpectedConstructor { position } => { + write!(f, "Expected a constructor at position: {:?}", position) + } + Self::ExpectedFieldsConstructor { position } => { write!( f, - "Expected a constructor, but got {} at position: {:?}", - actual, position + "Expected a fields constructor at position: {:?}", + position ) } Self::ExpectedFunction { actual, position } => { @@ -1318,8 +1290,6 @@ mod tests { #[test] fn assign_unit_struct_variable() { - env_logger::builder().is_test(true).try_init().unwrap(); - let input = " struct Foo; let x = Foo; @@ -1375,8 +1345,6 @@ mod tests { #[test] fn negate_expression() { - env_logger::builder().is_test(true).try_init().unwrap(); - let input = "let x = -42; -x"; assert_eq!(run(input), Ok(Some(Value::Integer(42))));