Fix errors

This commit is contained in:
Jeff 2024-03-17 17:39:39 -04:00
parent c3402394a2
commit bc5cadc446
9 changed files with 112 additions and 75 deletions

View File

@ -66,8 +66,8 @@ mod tests {
]); ]);
assert_eq!( assert_eq!(
block.run(&Context::new()), block.run(&Context::new()).unwrap(),
Ok(Action::Return(Value::integer(42))) Action::Return(Value::integer(42))
) )
} }

View File

@ -105,8 +105,9 @@ mod tests {
.with_position((0, 0))]), .with_position((0, 0))]),
None None
) )
.run(&Context::new()), .run(&Context::new())
Ok(Action::Return(Value::string("foo".to_string()))) .unwrap(),
Action::Return(Value::string("foo".to_string()))
) )
} }
@ -124,8 +125,9 @@ mod tests {
)) ))
.with_position((0, 0))])) .with_position((0, 0))]))
) )
.run(&Context::new()), .run(&Context::new())
Ok(Action::Return(Value::string("bar".to_string()))) .unwrap(),
Action::Return(Value::string("bar".to_string()))
) )
} }
} }

View File

@ -1,39 +0,0 @@
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

@ -47,25 +47,36 @@ impl AbstractTree for Logic {
Ok(()) Ok(())
} }
Logic::And(left, right) | Logic::Or(left, right) => { Logic::And(left, right) | Logic::Or(left, right) => {
let left = left.node.expected_type(context)?; let left_type = left.node.expected_type(context)?;
let right = right.node.expected_type(context)?; let right_type = right.node.expected_type(context)?;
if let (Type::Boolean, Type::Boolean) = (left, right) { if let Type::Boolean = left_type {
Ok(())
} else { } else {
Err(ValidationError::ExpectedBoolean { return Err(ValidationError::ExpectedBoolean {
actual: todo!(), actual: left_type,
position: todo!(), position: left.position,
}) });
} }
if let Type::Boolean = right_type {
} else {
return Err(ValidationError::ExpectedBoolean {
actual: right_type,
position: right.position,
});
}
Ok(())
} }
Logic::Not(expression) => { Logic::Not(expression) => {
if let Type::Boolean = expression.node.expected_type(context)? { let expression_type = expression.node.expected_type(context)?;
if let Type::Boolean = expression_type {
Ok(()) Ok(())
} else { } else {
Err(ValidationError::ExpectedBoolean { Err(ValidationError::ExpectedBoolean {
actual: todo!(), actual: expression_type,
position: todo!(), position: expression.position,
}) })
} }
} }

View File

@ -79,14 +79,16 @@ mod tests {
#[test] #[test]
fn basic_loop() { fn basic_loop() {
let result = Loop::new(vec![Statement::Break.with_position((0, 0))]).run(&Context::new()); let action = Loop::new(vec![Statement::Break.with_position((0, 0))])
.run(&Context::new())
.unwrap();
assert_eq!(result, Ok(Action::Break)) assert_eq!(action, Action::Break)
} }
#[test] #[test]
fn complex_loop() { fn complex_loop() {
let result = Block::new(vec![ let action = Block::new(vec![
Statement::Assignment(Assignment::new( Statement::Assignment(Assignment::new(
Identifier::new("i"), Identifier::new("i"),
None, None,
@ -116,8 +118,9 @@ mod tests {
Statement::Expression(Expression::Identifier(Identifier::new("i"))) Statement::Expression(Expression::Identifier(Identifier::new("i")))
.with_position((0, 0)), .with_position((0, 0)),
]) ])
.run(&Context::new()); .run(&Context::new())
.unwrap();
assert_eq!(result, Ok(Action::Return(Value::integer(3)))) assert_eq!(action, Action::Return(Value::integer(3)))
} }
} }

View File

@ -75,7 +75,7 @@ mod tests {
#[test] #[test]
fn simple_while_loop() { fn simple_while_loop() {
let result = Statement::Block(Block::new(vec![ let action = Statement::Block(Block::new(vec![
Statement::Assignment(Assignment::new( Statement::Assignment(Assignment::new(
Identifier::new("i"), Identifier::new("i"),
None, None,
@ -103,8 +103,9 @@ mod tests {
Statement::Expression(Expression::Identifier(Identifier::new("i"))) Statement::Expression(Expression::Identifier(Identifier::new("i")))
.with_position((0, 0)), .with_position((0, 0)),
])) ]))
.run(&Context::new()); .run(&Context::new())
.unwrap();
assert_eq!(result, Ok(Action::Return(Value::integer(3)))) assert_eq!(action, Action::Return(Value::integer(3)))
} }
} }

View File

@ -1,4 +1,4 @@
use std::{ops::Range, sync::PoisonError}; use std::{io, ops::Range, sync::PoisonError};
use ariadne::{Label, ReportBuilder}; use ariadne::{Label, ReportBuilder};
use chumsky::{prelude::Rich, span::Span}; use chumsky::{prelude::Rich, span::Span};
@ -62,6 +62,7 @@ impl Error {
"The interpreter failed to catch this error during validation.", "The interpreter failed to catch this error during validation.",
)); ));
} }
RuntimeError::Io(_) => todo!(),
}, },
Error::Validation { error, position } => match error { Error::Validation { error, position } => match error {
ValidationError::ExpectedBoolean { actual, position } => { ValidationError::ExpectedBoolean { actual, position } => {
@ -101,7 +102,7 @@ impl Error {
ValidationError::CannotIndex(_) => todo!(), ValidationError::CannotIndex(_) => todo!(),
ValidationError::CannotIndexWith(_, _) => todo!(), ValidationError::CannotIndexWith(_, _) => todo!(),
ValidationError::InterpreterExpectedReturn => todo!(), ValidationError::InterpreterExpectedReturn => todo!(),
ValidationError::ExpectedFunction { actual, position } => todo!(), ValidationError::ExpectedFunction { .. } => todo!(),
ValidationError::ExpectedValue => todo!(), ValidationError::ExpectedValue => todo!(),
}, },
} }
@ -128,8 +129,9 @@ impl<'src> From<Rich<'_, Token<'src>>> for Error {
} }
} }
#[derive(Debug, PartialEq)] #[derive(Debug)]
pub enum RuntimeError { pub enum RuntimeError {
Io(io::Error),
RwLockPoison(RwLockPoisonError), RwLockPoison(RwLockPoisonError),
ValidationFailure(ValidationError), ValidationFailure(ValidationError),
} }
@ -146,6 +148,25 @@ impl From<ValidationError> for RuntimeError {
} }
} }
impl From<io::Error> for RuntimeError {
fn from(error: io::Error) -> Self {
RuntimeError::Io(error)
}
}
impl PartialEq for RuntimeError {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(RuntimeError::Io(_), RuntimeError::Io(_)) => false,
(RuntimeError::RwLockPoison(_), RuntimeError::RwLockPoison(_)) => true,
(RuntimeError::ValidationFailure(left), RuntimeError::ValidationFailure(right)) => {
left == right
}
_ => false,
}
}
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum ValidationError { pub enum ValidationError {
CannotIndex(Type), CannotIndex(Type),

View File

@ -2,6 +2,7 @@ use std::{
cmp::Ordering, cmp::Ordering,
collections::BTreeMap, collections::BTreeMap,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
io::stdin,
ops::Range, ops::Range,
sync::{Arc, OnceLock}, sync::{Arc, OnceLock},
}; };
@ -322,6 +323,7 @@ pub struct ParsedFunction {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum BuiltInFunction { pub enum BuiltInFunction {
Output, Output,
ReadLine,
} }
impl BuiltInFunction { impl BuiltInFunction {
@ -333,12 +335,24 @@ impl BuiltInFunction {
.clone() .clone()
} }
pub fn read_line() -> Value {
static READ_LINE: OnceLock<Value> = OnceLock::new();
READ_LINE
.get_or_init(|| Value::built_in_function(BuiltInFunction::ReadLine))
.clone()
}
pub fn r#type(&self) -> Type { pub fn r#type(&self) -> Type {
match self { match self {
BuiltInFunction::Output => Type::Function { BuiltInFunction::Output => Type::Function {
parameter_types: vec![Type::Any], parameter_types: vec![Type::Any],
return_type: Box::new(Type::None), return_type: Box::new(Type::None),
}, },
BuiltInFunction::ReadLine => Type::Function {
parameter_types: Vec::with_capacity(0),
return_type: Box::new(Type::String),
},
} }
} }
@ -349,6 +363,13 @@ impl BuiltInFunction {
Ok(Action::None) Ok(Action::None)
} }
BuiltInFunction::ReadLine => {
let mut input = String::new();
stdin().read_line(&mut input)?;
Ok(Action::Return(Value::string(input)))
}
} }
} }
} }
@ -357,6 +378,23 @@ impl Display for BuiltInFunction {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
BuiltInFunction::Output => write!(f, "(to_output : any) : none rust_magic();"), BuiltInFunction::Output => write!(f, "(to_output : any) : none rust_magic();"),
BuiltInFunction::ReadLine => todo!(),
} }
} }
} }
pub enum BuiltInValue {
Io,
}
impl BuiltInValue {
pub fn io() -> Value {
static IO: OnceLock<Value> = OnceLock::new();
let mut properties = BTreeMap::new();
properties.insert(Identifier::new("read_line"), BuiltInFunction::read_line());
IO.get_or_init(|| Value::map(properties)).clone()
}
}

View File

@ -2,26 +2,26 @@ use dust_lang::*;
#[test] #[test]
fn logic() { fn logic() {
assert_eq!(interpret("1 == 1"), Ok(Some(Value::boolean(true)))); assert_eq!(interpret("1 == 1").unwrap(), Some(Value::boolean(true)));
assert_eq!( assert_eq!(
interpret("('42' == '42') && (42 != 0)"), interpret("('42' == '42') && (42 != 0)").unwrap(),
Ok(Some(Value::boolean(true))) Some(Value::boolean(true))
); );
} }
#[test] #[test]
fn math() { fn math() {
assert_eq!(interpret("1 + 1"), Ok(Some(Value::integer(2)))); assert_eq!(interpret("1 + 1").unwrap(), Some(Value::integer(2)));
assert_eq!( assert_eq!(
interpret("2 * (21 + 19 + 1 * 2) / 2"), interpret("2 * (21 + 19 + 1 * 2) / 2").unwrap(),
Ok(Some(Value::integer(42))) Some(Value::integer(42))
); );
} }
#[test] #[test]
fn list_index() { fn list_index() {
assert_eq!( assert_eq!(
interpret("foo = [1, 2, 3]; foo.2"), interpret("foo = [1, 2, 3]; foo.2").unwrap(),
Ok(Some(Value::integer(3))) Some(Value::integer(3))
); );
} }