Pass VM tests

This commit is contained in:
Jeff 2024-08-20 04:12:43 -04:00
parent d5c2ae92c9
commit c0ab5a84a2
3 changed files with 42 additions and 93 deletions

View File

@ -289,10 +289,6 @@ impl<'a> Analyzer<'a> {
} }
}, },
Expression::Struct(struct_expression) => match struct_expression.inner.as_ref() { 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 } => { StructExpression::Fields { name, fields } => {
self.context self.context
.update_last_position(&name.inner, name.position); .update_last_position(&name.inner, name.position);

View File

@ -407,9 +407,6 @@ impl Expression {
fields: types, fields: types,
})) }))
} }
StructExpression::Unit { name } => Some(Type::Struct(StructType::Unit {
name: name.inner.clone(),
})),
}, },
Expression::TupleAccess(tuple_access_expression) => { Expression::TupleAccess(tuple_access_expression) => {
let TupleAccessExpression { tuple, index } = tuple_access_expression.inner.as_ref(); 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<i64> for LiteralExpression { impl From<i64> for LiteralExpression {
fn from(value: i64) -> Self { fn from(value: i64) -> Self {
LiteralExpression::Primitive(PrimitiveValueExpression::Integer(value)) LiteralExpression::Primitive(PrimitiveValueExpression::Integer(value))
@ -664,13 +652,13 @@ impl From<i64> for LiteralExpression {
impl From<String> for LiteralExpression { impl From<String> for LiteralExpression {
fn from(value: String) -> Self { fn from(value: String) -> Self {
LiteralExpression::String(RawStringExpression(value)) LiteralExpression::String(value)
} }
} }
impl From<&str> for LiteralExpression { impl From<&str> for LiteralExpression {
fn from(value: &str) -> Self { fn from(value: &str) -> Self {
LiteralExpression::String(RawStringExpression(value.to_string())) LiteralExpression::String(value.to_string())
} }
} }
@ -695,7 +683,7 @@ impl From<char> for LiteralExpression {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum LiteralExpression { pub enum LiteralExpression {
Primitive(PrimitiveValueExpression), Primitive(PrimitiveValueExpression),
String(RawStringExpression), String(String),
} }
impl Display for LiteralExpression { impl Display for LiteralExpression {
@ -1022,10 +1010,8 @@ impl Display for LoopExpression {
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum StructExpression { pub enum StructExpression {
// The tuple struct expression is omitted because it is redundant with call expression // The unit struct is omitted because it is redundant with a plain identifier
Unit { // The tuple struct is omitted because it is redundant with the call expression
name: Node<Identifier>,
},
Fields { Fields {
name: Node<Identifier>, name: Node<Identifier>,
fields: Vec<(Node<Identifier>, Expression)>, fields: Vec<(Node<Identifier>, Expression)>,
@ -1035,7 +1021,6 @@ pub enum StructExpression {
impl Display for StructExpression { impl Display for StructExpression {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
StructExpression::Unit { name } => write!(f, "{}", name),
StructExpression::Fields { name, fields } => { StructExpression::Fields { name, fields } => {
write!(f, "{} {{", name)?; write!(f, "{} {{", name)?;

View File

@ -17,9 +17,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, MapExpression, MathOperator, Node, LiteralExpression, LogicOperator, LoopExpression, MapExpression, MathOperator, Node,
OperatorExpression, PrimitiveValueExpression, RangeExpression, RawStringExpression, Span, OperatorExpression, PrimitiveValueExpression, RangeExpression, Span, Statement,
Statement, StructDefinition, StructExpression, StructDefinition, StructExpression,
}, },
constructor::FieldsConstructor,
parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, DustError, parse, Analyzer, BuiltInFunctionError, Constructor, Context, ContextData, DustError,
Expression, Identifier, ParseError, Struct, StructType, Type, Value, ValueError, Expression, Identifier, ParseError, Struct, StructType, Type, Value, ValueError,
}; };
@ -281,67 +282,32 @@ impl Vm {
) -> Result<Evaluation, RuntimeError> { ) -> Result<Evaluation, RuntimeError> {
log::debug!("Running struct expression: {struct_expression}"); log::debug!("Running struct expression: {struct_expression}");
match struct_expression { let StructExpression::Fields { name, fields } = 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,
}
})?;
if let Type::Struct(StructType::Unit { name }) = r#type { let position = name.position;
Ok(Evaluation::Return(Some(Value::Struct(Struct::Unit { let constructor = self.context.get_constructor(&name.inner);
name,
})))) if let Some(constructor) = constructor {
} else { if let Constructor::Fields(fields_constructor) = constructor {
Err(RuntimeError::ExpectedType { let mut arguments = HashMap::with_capacity(fields.len());
expected: Type::Struct(StructType::Unit { name: name.inner }),
actual: r#type, for (identifier, expression) in fields {
position, let position = expression.position();
}) let value = self
} .run_expression(expression, collect_garbage)?
} .expect_value(position)?;
StructExpression::Fields {
name, arguments.insert(identifier.inner, value);
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,
})
} }
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<Evaluation, RuntimeError> { fn run_literal(&self, literal: LiteralExpression) -> Result<Evaluation, RuntimeError> {
let value = match literal { let value = match literal {
LiteralExpression::String(RawStringExpression(string)) => Value::String(string), LiteralExpression::String(string) => Value::String(string),
LiteralExpression::Primitive(primitive_expression) => match primitive_expression { LiteralExpression::Primitive(primitive_expression) => match primitive_expression {
PrimitiveValueExpression::Boolean(boolean) => Value::Boolean(boolean), PrimitiveValueExpression::Boolean(boolean) => Value::Boolean(boolean),
PrimitiveValueExpression::Character(character) => Value::Character(character), PrimitiveValueExpression::Character(character) => Value::Character(character),
@ -978,7 +944,9 @@ pub enum RuntimeError {
position: Span, position: Span,
}, },
ExpectedConstructor { ExpectedConstructor {
actual: Type, position: Span,
},
ExpectedFieldsConstructor {
position: Span, position: Span,
}, },
ExpectedIdentifier { ExpectedIdentifier {
@ -1052,6 +1020,7 @@ impl RuntimeError {
Self::EnumVariantNotFound { position, .. } => *position, Self::EnumVariantNotFound { position, .. } => *position,
Self::ExpectedBoolean { position } => *position, Self::ExpectedBoolean { position } => *position,
Self::ExpectedConstructor { position, .. } => *position, Self::ExpectedConstructor { position, .. } => *position,
Self::ExpectedFieldsConstructor { position } => *position,
Self::ExpectedFunction { position, .. } => *position, Self::ExpectedFunction { position, .. } => *position,
Self::ExpectedIdentifier { position } => *position, Self::ExpectedIdentifier { position } => *position,
Self::ExpectedIdentifierOrString { position } => *position, Self::ExpectedIdentifierOrString { position } => *position,
@ -1128,11 +1097,14 @@ impl Display for RuntimeError {
Self::ExpectedBoolean { position } => { Self::ExpectedBoolean { position } => {
write!(f, "Expected a boolean at position: {:?}", 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!( write!(
f, f,
"Expected a constructor, but got {} at position: {:?}", "Expected a fields constructor at position: {:?}",
actual, position position
) )
} }
Self::ExpectedFunction { actual, position } => { Self::ExpectedFunction { actual, position } => {
@ -1318,8 +1290,6 @@ mod tests {
#[test] #[test]
fn assign_unit_struct_variable() { fn assign_unit_struct_variable() {
env_logger::builder().is_test(true).try_init().unwrap();
let input = " let input = "
struct Foo; struct Foo;
let x = Foo; let x = Foo;
@ -1375,8 +1345,6 @@ mod tests {
#[test] #[test]
fn negate_expression() { fn negate_expression() {
env_logger::builder().is_test(true).try_init().unwrap();
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))));