Fix errors
This commit is contained in:
parent
c3402394a2
commit
bc5cadc446
@ -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))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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!()
|
|
||||||
}
|
|
||||||
}
|
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
src/error.rs
27
src/error.rs
@ -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),
|
||||||
|
38
src/value.rs
38
src/value.rs
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user