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() {
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);

View File

@ -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<i64> for LiteralExpression {
fn from(value: i64) -> Self {
LiteralExpression::Primitive(PrimitiveValueExpression::Integer(value))
@ -664,13 +652,13 @@ impl From<i64> for LiteralExpression {
impl From<String> 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<char> 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<Identifier>,
},
// 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<Identifier>,
fields: Vec<(Node<Identifier>, 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)?;

View File

@ -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<Evaluation, RuntimeError> {
log::debug!("Running struct expression: {struct_expression}");
match struct_expression {
StructExpression::Unit { name } => {
let StructExpression::Fields { name, fields } = struct_expression;
let position = name.position;
let r#type = self.context.get_type(&name.inner).ok_or_else(|| {
RuntimeError::UndefinedType {
identifier: name.inner.clone(),
position,
}
})?;
let constructor = self.context.get_constructor(&name.inner);
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 Some(constructor) = constructor {
if let Constructor::Fields(fields_constructor) = constructor {
let mut arguments = HashMap::with_capacity(fields.len());
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();
for (identifier, expression) in fields {
let position = expression.position();
let value = self
.run_expression(expression, collect_garbage)?
.expect_value(expression_position)?;
.expect_value(position)?;
values.insert(identifier.inner, value);
arguments.insert(identifier.inner, value);
}
Ok(Evaluation::Return(Some(Value::Struct(Struct::Fields {
name,
fields: values,
}))))
Ok(Evaluation::Return(Some(
fields_constructor.construct(arguments),
)))
} else {
Err(RuntimeError::ExpectedType {
expected: Type::Struct(StructType::Fields {
name: name.inner,
fields: Default::default(),
}),
actual: r#type,
position,
})
}
Err(RuntimeError::ExpectedFieldsConstructor { position })
}
} else {
Err(RuntimeError::ExpectedConstructor { position })
}
}
@ -643,7 +609,7 @@ impl Vm {
fn run_literal(&self, literal: LiteralExpression) -> Result<Evaluation, RuntimeError> {
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))));