Begin using Positioned type

This commit is contained in:
Jeff 2024-03-17 00:49:01 -04:00
parent 15b1808741
commit e9bfd9f1f8
11 changed files with 197 additions and 169 deletions

View File

@ -3,14 +3,14 @@ use crate::{
Context, Context,
}; };
use super::{AbstractTree, Action, Identifier, Statement, Type}; use super::{AbstractTree, Action, Identifier, Positioned, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Assignment { pub struct Assignment {
identifier: Identifier, identifier: Identifier,
r#type: Option<Type>, r#type: Option<Positioned<Type>>,
operator: AssignmentOperator, operator: AssignmentOperator,
statement: Box<Statement>, statement: Box<Positioned<Statement>>,
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
@ -23,9 +23,9 @@ pub enum AssignmentOperator {
impl Assignment { impl Assignment {
pub fn new( pub fn new(
identifier: Identifier, identifier: Identifier,
r#type: Option<Type>, r#type: Option<Positioned<Type>>,
operator: AssignmentOperator, operator: AssignmentOperator,
statement: Statement, statement: Positioned<Statement>,
) -> Self { ) -> Self {
Self { Self {
identifier, identifier,
@ -42,24 +42,34 @@ impl AbstractTree for Assignment {
} }
fn validate(&self, context: &Context) -> Result<(), ValidationError> { fn validate(&self, context: &Context) -> Result<(), ValidationError> {
let statement_type = self.statement.expected_type(context)?; let statement_type = self.statement.node.expected_type(context)?;
if let Some(expected) = &self.r#type { if let Some(Positioned {
expected.check(&statement_type)?; node: expected_type,
position: expected_position,
}) = &self.r#type
{
expected_type.check(&statement_type).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: self.statement.position,
expected_position: expected_position.clone(),
}
})?;
context.set_type(self.identifier.clone(), expected.clone())?; context.set_type(self.identifier.clone(), expected_type.clone())?;
} else { } else {
context.set_type(self.identifier.clone(), statement_type)?; context.set_type(self.identifier.clone(), statement_type)?;
} }
self.identifier.validate(context)?; self.identifier.validate(context)?;
self.statement.validate(context)?; self.statement.node.validate(context)?;
Ok(()) Ok(())
} }
fn run(self, context: &Context) -> Result<Action, RuntimeError> { fn run(self, context: &Context) -> Result<Action, RuntimeError> {
let action = self.statement.run(context)?; let action = self.statement.node.run(context)?;
let value = match action { let value = match action {
Action::Return(value) => value, Action::Return(value) => value,
r#break => return Ok(r#break), r#break => return Ok(r#break),
@ -101,7 +111,7 @@ impl AbstractTree for Assignment {
mod tests { mod tests {
use crate::{ use crate::{
abstract_tree::{Expression, ValueNode}, abstract_tree::{Expression, ValueNode},
error::TypeCheckError, error::TypeConflict,
Value, Value,
}; };
@ -115,7 +125,10 @@ mod tests {
Identifier::new("foobar"), Identifier::new("foobar"),
None, None,
AssignmentOperator::Assign, AssignmentOperator::Assign,
Statement::expression(Expression::Value(ValueNode::Integer(42)), (0..0).into()), Positioned {
node: Statement::Expression(Expression::Value(ValueNode::Integer(42))),
position: (0, 0),
},
) )
.run(&context) .run(&context)
.unwrap(); .unwrap();
@ -138,7 +151,10 @@ mod tests {
Identifier::new("foobar"), Identifier::new("foobar"),
None, None,
AssignmentOperator::AddAssign, AssignmentOperator::AddAssign,
Statement::expression(Expression::Value(ValueNode::Integer(41)), (0..0).into()), Positioned {
node: Statement::Expression(Expression::Value(ValueNode::Integer(41))),
position: (0, 0),
},
) )
.run(&context) .run(&context)
.unwrap(); .unwrap();
@ -161,7 +177,10 @@ mod tests {
Identifier::new("foobar"), Identifier::new("foobar"),
None, None,
AssignmentOperator::SubAssign, AssignmentOperator::SubAssign,
Statement::expression(Expression::Value(ValueNode::Integer(1)), (0..0).into()), Positioned {
node: Statement::Expression(Expression::Value(ValueNode::Integer(1))),
position: (0, 0),
},
) )
.run(&context) .run(&context)
.unwrap(); .unwrap();
@ -176,18 +195,28 @@ mod tests {
fn type_check() { fn type_check() {
let validation = Assignment::new( let validation = Assignment::new(
Identifier::new("foobar"), Identifier::new("foobar"),
Some(Type::Boolean), Some(Positioned {
node: Type::Boolean,
position: (0, 0),
}),
AssignmentOperator::Assign, AssignmentOperator::Assign,
Statement::expression(Expression::Value(ValueNode::Integer(42)), (0..0).into()), Positioned {
node: Statement::Expression(Expression::Value(ValueNode::Integer(42))),
position: (0, 0),
},
) )
.validate(&Context::new()); .validate(&Context::new());
assert_eq!( assert_eq!(
validation, validation,
Err(ValidationError::TypeCheck(TypeCheckError { Err(ValidationError::TypeCheck {
conflict: TypeConflict {
actual: Type::Integer, actual: Type::Integer,
expected: Type::Boolean expected: Type::Boolean
})) },
actual_position: (0, 0),
expected_position: (0, 0),
})
) )
} }
} }

View File

@ -61,9 +61,9 @@ mod tests {
#[test] #[test]
fn run_returns_value_of_final_statement() { fn run_returns_value_of_final_statement() {
let block = Block::new(vec![ let block = Block::new(vec![
Statement::expression(Expression::Value(ValueNode::Integer(1)), (0..0).into()), Statement::Expression(Expression::Value(ValueNode::Integer(1))),
Statement::expression(Expression::Value(ValueNode::Integer(2)), (0..0).into()), Statement::Expression(Expression::Value(ValueNode::Integer(2))),
Statement::expression(Expression::Value(ValueNode::Integer(42)), (0..0).into()), Statement::Expression(Expression::Value(ValueNode::Integer(42))),
]); ]);
assert_eq!( assert_eq!(
@ -75,11 +75,8 @@ mod tests {
#[test] #[test]
fn expected_type_returns_type_of_final_statement() { fn expected_type_returns_type_of_final_statement() {
let block = Block::new(vec![ let block = Block::new(vec![
Statement::expression( Statement::Expression(Expression::Value(ValueNode::String("42".to_string()))),
Expression::Value(ValueNode::String("42".to_string())), Statement::Expression(Expression::Value(ValueNode::Integer(42))),
(0..0).into(),
),
Statement::expression(Expression::Value(ValueNode::Integer(42)), (0..0).into()),
]); ]);
assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer)) assert_eq!(block.expected_type(&Context::new()), Ok(Type::Integer))

View File

@ -3,17 +3,21 @@ use crate::{
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
use super::{AbstractTree, Action, Block, Expression, Type}; use super::{AbstractTree, Action, Block, Expression, Positioned, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct IfElse { pub struct IfElse {
if_expression: Expression, if_expression: Positioned<Expression>,
if_block: Block, if_block: Positioned<Block>,
else_block: Option<Block>, else_block: Option<Positioned<Block>>,
} }
impl IfElse { impl IfElse {
pub fn new(if_expression: Expression, if_block: Block, else_block: Option<Block>) -> Self { pub fn new(
if_expression: Positioned<Expression>,
if_block: Positioned<Block>,
else_block: Option<Positioned<Block>>,
) -> Self {
Self { Self {
if_expression, if_expression,
if_block, if_block,
@ -24,16 +28,22 @@ impl IfElse {
impl AbstractTree for IfElse { impl AbstractTree for IfElse {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
self.if_block.expected_type(_context) self.if_block.node.expected_type(_context)
} }
fn validate(&self, context: &Context) -> Result<(), ValidationError> { fn validate(&self, context: &Context) -> Result<(), ValidationError> {
if let Type::Boolean = self.if_expression.expected_type(context)? { if let Type::Boolean = self.if_expression.node.expected_type(context)? {
if let Some(else_block) = &self.else_block { if let Some(else_block) = &self.else_block {
let expected = self.if_block.expected_type(context)?; let expected = self.if_block.node.expected_type(context)?;
let actual = else_block.expected_type(context)?; let actual = else_block.node.expected_type(context)?;
expected.check(&actual)?; expected
.check(&actual)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.if_block.position,
expected_position: self.if_expression.position,
})?;
} }
Ok(()) Ok(())
@ -45,14 +55,15 @@ impl AbstractTree for IfElse {
fn run(self, _context: &Context) -> Result<Action, RuntimeError> { fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let if_boolean = self let if_boolean = self
.if_expression .if_expression
.node
.run(_context)? .run(_context)?
.as_return_value()? .as_return_value()?
.as_boolean()?; .as_boolean()?;
if if_boolean { if if_boolean {
self.if_block.run(_context) self.if_block.node.run(_context)
} else if let Some(else_statement) = self.else_block { } else if let Some(else_statement) = self.else_block {
else_statement.run(_context) else_statement.node.run(_context)
} else { } else {
Ok(Action::None) Ok(Action::None)
} }
@ -72,11 +83,11 @@ mod tests {
fn simple_if() { fn simple_if() {
assert_eq!( assert_eq!(
IfElse::new( IfElse::new(
Expression::Value(ValueNode::Boolean(true)), Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
Block::new(vec![Statement::expression( Block::new(vec![Statement::Expression(Expression::Value(
Expression::Value(ValueNode::String("foo".to_string())), ValueNode::String("foo".to_string())
(0..0).into() ),)])
)]), .positioned((0, 0)),
None None
) )
.run(&Context::new()), .run(&Context::new()),
@ -88,15 +99,17 @@ mod tests {
fn simple_if_else() { fn simple_if_else() {
assert_eq!( assert_eq!(
IfElse::new( IfElse::new(
Expression::Value(ValueNode::Boolean(false)), Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)),
Block::new(vec![Statement::expression( Block::new(vec![Statement::Expression(Expression::Value(
Expression::Value(ValueNode::String("foo".to_string())), ValueNode::String("foo".to_string())
(0..0).into() ))])
),]), .positioned((0, 0)),
Some(Block::new(vec![Statement::expression( Some(
Expression::Value(ValueNode::String("bar".to_string())), Block::new(vec![Statement::Expression(Expression::Value(
(0..0).into() ValueNode::String("bar".to_string())
)])) ))])
.positioned((0, 0))
)
) )
.run(&Context::new()), .run(&Context::new()),
Ok(Action::Return(Value::string("bar".to_string()))) Ok(Action::Return(Value::string("bar".to_string())))

39
src/abstract_tree/item.rs Normal file
View File

@ -0,0 +1,39 @@
use super::{AbstractTree, Expression, Positioned, Statement};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Item {
Expression(Positioned<Expression>),
Statement(Positioned<Statement>),
}
impl Item {
pub fn position(&self) -> &(usize, usize) {
match self {
Item::Expression((_, position)) => position,
Item::Statement((_, position)) => position,
}
}
}
impl AbstractTree for Item {
fn expected_type(
&self,
context: &crate::context::Context,
) -> Result<super::Type, crate::error::ValidationError> {
todo!()
}
fn validate(
&self,
context: &crate::context::Context,
) -> Result<(), crate::error::ValidationError> {
todo!()
}
fn run(
self,
context: &crate::context::Context,
) -> Result<super::Action, crate::error::RuntimeError> {
todo!()
}
}

View File

@ -36,10 +36,23 @@ use crate::{
Value, Value,
}; };
pub trait AbstractTree { #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Positioned<T> {
pub node: T,
pub position: (usize, usize),
}
pub trait AbstractTree: Sized {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>; fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>;
fn validate(&self, context: &Context) -> Result<(), ValidationError>; fn validate(&self, context: &Context) -> Result<(), ValidationError>;
fn run(self, context: &Context) -> Result<Action, RuntimeError>; fn run(self, context: &Context) -> Result<Action, RuntimeError>;
fn positioned(self, position: (usize, usize)) -> Positioned<Self> {
Positioned {
node: self,
position,
}
}
} }
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]

View File

@ -8,72 +8,7 @@ use crate::{
use super::{AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Type, While}; use super::{AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, Type, While};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Statement { pub enum Statement {
pub inner: StatementInner,
pub span: (usize, usize),
}
impl Statement {
pub fn assignment(assignment: Assignment, span: SimpleSpan) -> Self {
Statement {
inner: StatementInner::Assignment(assignment),
span: (span.start(), span.end()),
}
}
pub fn block(block: Block, span: SimpleSpan) -> Self {
Statement {
inner: StatementInner::Block(block),
span: (span.start(), span.end()),
}
}
pub fn r#break(span: SimpleSpan) -> Self {
Statement {
inner: StatementInner::Break,
span: (span.start(), span.end()),
}
}
pub fn expression(expression: Expression, span: SimpleSpan) -> Self {
Statement {
inner: StatementInner::Expression(expression),
span: (span.start(), span.end()),
}
}
pub fn if_else(if_else: IfElse, span: SimpleSpan) -> Self {
Statement {
inner: StatementInner::IfElse(if_else),
span: (span.start(), span.end()),
}
}
pub fn r#loop(r#loop: Loop, span: SimpleSpan) -> Self {
Statement {
inner: StatementInner::Loop(r#loop),
span: (span.start(), span.end()),
}
}
pub fn r#while(r#while: While, span: SimpleSpan) -> Self {
Statement {
inner: StatementInner::While(r#while),
span: (span.start(), span.end()),
}
}
pub fn span(&self) -> (usize, usize) {
self.span
}
pub fn inner(&self) -> &StatementInner {
&self.inner
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum StatementInner {
Assignment(Assignment), Assignment(Assignment),
Block(Block), Block(Block),
Break, Break,
@ -85,7 +20,7 @@ pub enum StatementInner {
impl AbstractTree for Statement { impl AbstractTree for Statement {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match &self.inner { match self {
StatementInner::Assignment(assignment) => assignment.expected_type(_context), StatementInner::Assignment(assignment) => assignment.expected_type(_context),
StatementInner::Block(block) => block.expected_type(_context), StatementInner::Block(block) => block.expected_type(_context),
StatementInner::Break => Ok(Type::None), StatementInner::Break => Ok(Type::None),
@ -97,7 +32,7 @@ impl AbstractTree for Statement {
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
match &self.inner { match self {
StatementInner::Assignment(assignment) => assignment.validate(_context), StatementInner::Assignment(assignment) => assignment.validate(_context),
StatementInner::Block(block) => block.validate(_context), StatementInner::Block(block) => block.validate(_context),
StatementInner::Break => Ok(()), StatementInner::Break => Ok(()),
@ -109,7 +44,7 @@ impl AbstractTree for Statement {
} }
fn run(self, _context: &Context) -> Result<Action, RuntimeError> { fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
match self.inner { match self {
StatementInner::Assignment(assignment) => assignment.run(_context), StatementInner::Assignment(assignment) => assignment.run(_context),
StatementInner::Block(block) => block.run(_context), StatementInner::Block(block) => block.run(_context),
StatementInner::Break => Ok(Action::Break), StatementInner::Break => Ok(Action::Break),

View File

@ -3,7 +3,7 @@ use std::fmt::{self, Display, Formatter};
use crate::{ use crate::{
abstract_tree::Identifier, abstract_tree::Identifier,
context::Context, context::Context,
error::{RuntimeError, TypeCheckError, ValidationError}, error::{RuntimeError, TypeConflict, ValidationError},
}; };
use super::{AbstractTree, Action}; use super::{AbstractTree, Action};
@ -29,7 +29,7 @@ pub enum Type {
} }
impl Type { impl Type {
pub fn check(&self, other: &Type) -> Result<(), TypeCheckError> { pub fn check(&self, other: &Type) -> Result<(), TypeConflict> {
match (self, other) { match (self, other) {
(Type::Any, _) (Type::Any, _)
| (_, Type::Any) | (_, Type::Any)
@ -49,7 +49,7 @@ impl Type {
if left == right { if left == right {
Ok(()) Ok(())
} else { } else {
Err(TypeCheckError { Err(TypeConflict {
actual: other.clone(), actual: other.clone(),
expected: self.clone(), expected: self.clone(),
}) })
@ -59,7 +59,7 @@ impl Type {
if let Ok(()) = left.check(right) { if let Ok(()) = left.check(right) {
Ok(()) Ok(())
} else { } else {
Err(TypeCheckError { Err(TypeConflict {
actual: left.as_ref().clone(), actual: left.as_ref().clone(),
expected: right.as_ref().clone(), expected: right.as_ref().clone(),
}) })
@ -86,7 +86,7 @@ impl Type {
Ok(()) Ok(())
} }
_ => Err(TypeCheckError { _ => Err(TypeConflict {
actual: other.clone(), actual: other.clone(),
expected: self.clone(), expected: self.clone(),
}), }),
@ -188,14 +188,14 @@ mod tests {
assert_eq!( assert_eq!(
foo.check(&bar), foo.check(&bar),
Err(TypeCheckError { Err(TypeConflict {
actual: bar.clone(), actual: bar.clone(),
expected: foo.clone() expected: foo.clone()
}) })
); );
assert_eq!( assert_eq!(
bar.check(&foo), bar.check(&foo),
Err(TypeCheckError { Err(TypeConflict {
actual: foo.clone(), actual: foo.clone(),
expected: bar.clone() expected: bar.clone()
}) })
@ -222,7 +222,7 @@ mod tests {
assert_eq!( assert_eq!(
left.check(right), left.check(right),
Err(TypeCheckError { Err(TypeConflict {
actual: right.clone(), actual: right.clone(),
expected: left.clone() expected: left.clone()
}) })

View File

@ -19,10 +19,7 @@ pub enum Error {
span: (usize, usize), span: (usize, usize),
}, },
Runtime(RuntimeError), Runtime(RuntimeError),
Validation { Validation(ValidationError),
error: ValidationError,
span: (usize, usize),
},
} }
impl Error { impl Error {
@ -49,33 +46,38 @@ impl Error {
.finish() .finish()
} }
Error::Runtime(_) => todo!(), Error::Runtime(_) => todo!(),
Error::Validation { error, span } => { Error::Validation(validation_error) => {
let mut report = Report::build( let mut report =
ReportKind::Custom("Validation Error", Color::White), Report::build(ReportKind::Custom("Validation Error", Color::White), (), 0);
(),
span.0,
);
match error { match validation_error {
ValidationError::ExpectedBoolean => { ValidationError::ExpectedBoolean => {
report = report.with_label( report =
Label::new(span.0..span.1).with_message("Expected boolean."), report.with_label(Label::new(0..0).with_message("Expected boolean."));
);
} }
ValidationError::ExpectedIntegerOrFloat => { ValidationError::ExpectedIntegerOrFloat => {
report = report.with_label( report = report.with_label(
Label::new(span.0..span.1).with_message("Expected integer or float."), Label::new(0..0).with_message("Expected integer or float."),
); );
} }
ValidationError::RwLockPoison(_) => todo!(), ValidationError::RwLockPoison(_) => todo!(),
ValidationError::TypeCheck(TypeCheckError { actual, expected }) => { ValidationError::TypeCheck {
report = report.with_label(Label::new(span.0..span.1).with_message( conflict,
format!("Type error. Expected {expected} but got {actual}."), actual_position,
)); expected_position: expected_postion,
} => {
let TypeConflict { actual, expected } = conflict;
report = report.with_labels([
Label::new(expected_postion.0..expected_postion.1)
.with_message(format!("Type {expected} established here.")),
Label::new(actual_position.0..actual_position.1)
.with_message(format!("Got type {actual} here.")),
]);
} }
ValidationError::VariableNotFound(identifier) => { ValidationError::VariableNotFound(identifier) => {
report = report report = report
.with_label(Label::new(span.0..span.1).with_message(format!( .with_label(Label::new(0..0).with_message(format!(
"The variable {identifier} does not exist." "The variable {identifier} does not exist."
))); )));
} }
@ -144,7 +146,16 @@ pub enum ValidationError {
ExpectedValue, ExpectedValue,
InterpreterExpectedReturn, InterpreterExpectedReturn,
RwLockPoison(RwLockPoisonError), RwLockPoison(RwLockPoisonError),
TypeCheck(TypeCheckError), TypeCheck {
/// The mismatch that caused the error.
conflict: TypeConflict,
/// The position of the item that gave the "actual" type.
actual_position: (usize, usize),
/// The position of the item that gave the "expected" type.
expected_position: (usize, usize),
},
VariableNotFound(Identifier), VariableNotFound(Identifier),
} }
@ -154,12 +165,6 @@ impl From<RwLockPoisonError> for ValidationError {
} }
} }
impl From<TypeCheckError> for ValidationError {
fn from(error: TypeCheckError) -> Self {
ValidationError::TypeCheck(error)
}
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct RwLockPoisonError; pub struct RwLockPoisonError;
@ -170,7 +175,7 @@ impl<T> From<PoisonError<T>> for RwLockPoisonError {
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct TypeCheckError { pub struct TypeConflict {
pub actual: Type, pub actual: Type,
pub expected: Type, pub expected: Type,
} }

View File

@ -36,11 +36,8 @@ impl Interpreter {
.filter_map(|statement| { .filter_map(|statement| {
statement statement
.validate(&self.context) .validate(&self.context)
.map_err(|validation_error| Error::Validation {
error: validation_error,
span: statement.span(),
})
.err() .err()
.map(|validation_error| Error::Validation(validation_error))
}) })
.collect::<Vec<Error>>(); .collect::<Vec<Error>>();

View File

@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use dust_lang::{ use dust_lang::{
abstract_tree::{Identifier, Type}, abstract_tree::{Identifier, Type},
error::{Error, TypeCheckError, ValidationError}, error::{Error, TypeConflict, ValidationError},
*, *,
}; };
@ -136,7 +136,7 @@ fn map_type_errors() {
assert_eq!( assert_eq!(
interpret("{ foo : bool = 'bar' }"), interpret("{ foo : bool = 'bar' }"),
Err(vec![Error::Validation { Err(vec![Error::Validation {
error: ValidationError::TypeCheck(TypeCheckError { error: ValidationError::TypeCheck(TypeConflict {
actual: Type::String, actual: Type::String,
expected: Type::Boolean expected: Type::Boolean
}), }),

View File

@ -1,6 +1,6 @@
use dust_lang::{ use dust_lang::{
abstract_tree::{Block, Expression, Identifier, Statement, Type}, abstract_tree::{Block, Expression, Identifier, Statement, Type},
error::{Error, TypeCheckError, ValidationError}, error::{Error, TypeConflict, ValidationError},
*, *,
}; };
@ -25,7 +25,7 @@ fn set_variable_with_type_error() {
assert_eq!( assert_eq!(
interpret("foobar: str = true"), interpret("foobar: str = true"),
Err(vec![Error::Validation { Err(vec![Error::Validation {
error: ValidationError::TypeCheck(TypeCheckError { error: ValidationError::TypeCheck(TypeConflict {
actual: Type::Boolean, actual: Type::Boolean,
expected: Type::String expected: Type::String
}), }),