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!(
block.run(&Context::new()),
Ok(Action::Return(Value::integer(42)))
block.run(&Context::new()).unwrap(),
Action::Return(Value::integer(42))
)
}

View File

@ -105,8 +105,9 @@ mod tests {
.with_position((0, 0))]),
None
)
.run(&Context::new()),
Ok(Action::Return(Value::string("foo".to_string())))
.run(&Context::new())
.unwrap(),
Action::Return(Value::string("foo".to_string()))
)
}
@ -124,8 +125,9 @@ mod tests {
))
.with_position((0, 0))]))
)
.run(&Context::new()),
Ok(Action::Return(Value::string("bar".to_string())))
.run(&Context::new())
.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(())
}
Logic::And(left, right) | Logic::Or(left, right) => {
let left = left.node.expected_type(context)?;
let right = right.node.expected_type(context)?;
let left_type = left.node.expected_type(context)?;
let right_type = right.node.expected_type(context)?;
if let (Type::Boolean, Type::Boolean) = (left, right) {
Ok(())
if let Type::Boolean = left_type {
} else {
Err(ValidationError::ExpectedBoolean {
actual: todo!(),
position: todo!(),
})
return Err(ValidationError::ExpectedBoolean {
actual: left_type,
position: left.position,
});
}
if let Type::Boolean = right_type {
} else {
return Err(ValidationError::ExpectedBoolean {
actual: right_type,
position: right.position,
});
}
Ok(())
}
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(())
} else {
Err(ValidationError::ExpectedBoolean {
actual: todo!(),
position: todo!(),
actual: expression_type,
position: expression.position,
})
}
}

View File

@ -79,14 +79,16 @@ mod tests {
#[test]
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]
fn complex_loop() {
let result = Block::new(vec![
let action = Block::new(vec![
Statement::Assignment(Assignment::new(
Identifier::new("i"),
None,
@ -116,8 +118,9 @@ mod tests {
Statement::Expression(Expression::Identifier(Identifier::new("i")))
.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]
fn simple_while_loop() {
let result = Statement::Block(Block::new(vec![
let action = Statement::Block(Block::new(vec![
Statement::Assignment(Assignment::new(
Identifier::new("i"),
None,
@ -103,8 +103,9 @@ mod tests {
Statement::Expression(Expression::Identifier(Identifier::new("i")))
.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 chumsky::{prelude::Rich, span::Span};
@ -62,6 +62,7 @@ impl Error {
"The interpreter failed to catch this error during validation.",
));
}
RuntimeError::Io(_) => todo!(),
},
Error::Validation { error, position } => match error {
ValidationError::ExpectedBoolean { actual, position } => {
@ -101,7 +102,7 @@ impl Error {
ValidationError::CannotIndex(_) => todo!(),
ValidationError::CannotIndexWith(_, _) => todo!(),
ValidationError::InterpreterExpectedReturn => todo!(),
ValidationError::ExpectedFunction { actual, position } => todo!(),
ValidationError::ExpectedFunction { .. } => todo!(),
ValidationError::ExpectedValue => todo!(),
},
}
@ -128,8 +129,9 @@ impl<'src> From<Rich<'_, Token<'src>>> for Error {
}
}
#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum RuntimeError {
Io(io::Error),
RwLockPoison(RwLockPoisonError),
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)]
pub enum ValidationError {
CannotIndex(Type),

View File

@ -2,6 +2,7 @@ use std::{
cmp::Ordering,
collections::BTreeMap,
fmt::{self, Display, Formatter},
io::stdin,
ops::Range,
sync::{Arc, OnceLock},
};
@ -322,6 +323,7 @@ pub struct ParsedFunction {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum BuiltInFunction {
Output,
ReadLine,
}
impl BuiltInFunction {
@ -333,12 +335,24 @@ impl BuiltInFunction {
.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 {
match self {
BuiltInFunction::Output => Type::Function {
parameter_types: vec![Type::Any],
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)
}
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 {
match self {
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]
fn logic() {
assert_eq!(interpret("1 == 1"), Ok(Some(Value::boolean(true))));
assert_eq!(interpret("1 == 1").unwrap(), Some(Value::boolean(true)));
assert_eq!(
interpret("('42' == '42') && (42 != 0)"),
Ok(Some(Value::boolean(true)))
interpret("('42' == '42') && (42 != 0)").unwrap(),
Some(Value::boolean(true))
);
}
#[test]
fn math() {
assert_eq!(interpret("1 + 1"), Ok(Some(Value::integer(2))));
assert_eq!(interpret("1 + 1").unwrap(), Some(Value::integer(2)));
assert_eq!(
interpret("2 * (21 + 19 + 1 * 2) / 2"),
Ok(Some(Value::integer(42)))
interpret("2 * (21 + 19 + 1 * 2) / 2").unwrap(),
Some(Value::integer(42))
);
}
#[test]
fn list_index() {
assert_eq!(
interpret("foo = [1, 2, 3]; foo.2"),
Ok(Some(Value::integer(3)))
interpret("foo = [1, 2, 3]; foo.2").unwrap(),
Some(Value::integer(3))
);
}