Pass VM tests
This commit is contained in:
parent
d5c2ae92c9
commit
c0ab5a84a2
@ -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);
|
||||||
|
@ -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)?;
|
||||||
|
|
||||||
|
@ -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))));
|
||||||
|
Loading…
Reference in New Issue
Block a user