Add tests
This commit is contained in:
parent
0c1a2f4499
commit
a92074a77b
@ -131,6 +131,7 @@ pub fn lexer<'src>() -> impl Parser<
|
||||
.or_not()
|
||||
.then(text::int(10))
|
||||
.then(just('.').then(text::digits(10)))
|
||||
.then(just('e').then(text::digits(10)).or_not())
|
||||
.to_slice()
|
||||
.map(|text: &str| Token::Float(text.parse().unwrap()));
|
||||
|
||||
|
56
src/value.rs
56
src/value.rs
@ -143,22 +143,54 @@ impl Value {
|
||||
}
|
||||
|
||||
pub fn add(&self, other: &Self) -> Result<Value, ValidationError> {
|
||||
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
||||
(self.inner().as_ref(), other.inner().as_ref())
|
||||
{
|
||||
Ok(Value::integer(left + right))
|
||||
} else {
|
||||
Err(ValidationError::ExpectedIntegerOrFloat)
|
||||
match (self.inner().as_ref(), other.inner().as_ref()) {
|
||||
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
||||
let sum = left.saturating_add(*right);
|
||||
|
||||
Ok(Value::integer(sum))
|
||||
}
|
||||
(ValueInner::Float(left), ValueInner::Float(right)) => {
|
||||
let sum = left + right;
|
||||
|
||||
Ok(Value::float(sum))
|
||||
}
|
||||
(ValueInner::Float(left), ValueInner::Integer(right)) => {
|
||||
let sum = left + *right as f64;
|
||||
|
||||
Ok(Value::float(sum))
|
||||
}
|
||||
(ValueInner::Integer(left), ValueInner::Float(right)) => {
|
||||
let sum = *left as f64 + right;
|
||||
|
||||
Ok(Value::float(sum))
|
||||
}
|
||||
_ => Err(ValidationError::ExpectedIntegerOrFloat),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subtract(&self, other: &Self) -> Result<Value, ValidationError> {
|
||||
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
|
||||
(self.inner().as_ref(), other.inner().as_ref())
|
||||
{
|
||||
Ok(Value::integer(left - right))
|
||||
} else {
|
||||
Err(ValidationError::ExpectedIntegerOrFloat)
|
||||
match (self.inner().as_ref(), other.inner().as_ref()) {
|
||||
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
||||
let sum = left.saturating_sub(*right);
|
||||
|
||||
Ok(Value::integer(sum))
|
||||
}
|
||||
(ValueInner::Float(left), ValueInner::Float(right)) => {
|
||||
let sum = left - right;
|
||||
|
||||
Ok(Value::float(sum))
|
||||
}
|
||||
(ValueInner::Float(left), ValueInner::Integer(right)) => {
|
||||
let sum = left - *right as f64;
|
||||
|
||||
Ok(Value::float(sum))
|
||||
}
|
||||
(ValueInner::Integer(left), ValueInner::Float(right)) => {
|
||||
let sum = *left as f64 - right;
|
||||
|
||||
Ok(Value::float(sum))
|
||||
}
|
||||
_ => Err(ValidationError::ExpectedIntegerOrFloat),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
151
tests/values.rs
Normal file
151
tests/values.rs
Normal file
@ -0,0 +1,151 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use dust_lang::{
|
||||
abstract_tree::{Identifier, Type},
|
||||
error::{Error, TypeCheckError, ValidationError},
|
||||
*,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn none() {
|
||||
assert_eq!(interpret("x = 9"), Ok(None));
|
||||
assert_eq!(interpret("x = 1 + 1"), Ok(None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer() {
|
||||
assert_eq!(interpret("1"), Ok(Some(Value::integer(1))));
|
||||
assert_eq!(interpret("123"), Ok(Some(Value::integer(123))));
|
||||
assert_eq!(interpret("-666"), Ok(Some(Value::integer(-666))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_saturation() {
|
||||
assert_eq!(
|
||||
interpret("9223372036854775807 + 1"),
|
||||
Ok(Some(Value::integer(i64::MAX)))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("-9223372036854775808 - 1"),
|
||||
Ok(Some(Value::integer(i64::MIN)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float() {
|
||||
assert_eq!(
|
||||
interpret("1.7976931348623157e308"),
|
||||
Ok(Some(Value::float(f64::MAX)))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("-1.7976931348623157e308"),
|
||||
Ok(Some(Value::float(f64::MIN)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_saturation() {
|
||||
assert_eq!(
|
||||
interpret("1.7976931348623157e308 + 1"),
|
||||
Ok(Some(Value::float(f64::MAX)))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("-1.7976931348623157e308 - 1"),
|
||||
Ok(Some(Value::float(f64::MIN)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string() {
|
||||
assert_eq!(
|
||||
interpret("\"one\""),
|
||||
Ok(Some(Value::string("one".to_string())))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("'one'"),
|
||||
Ok(Some(Value::string("one".to_string())))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("`one`"),
|
||||
Ok(Some(Value::string("one".to_string())))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("`'one'`"),
|
||||
Ok(Some(Value::string("'one'".to_string())))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("'`one`'"),
|
||||
Ok(Some(Value::string("`one`".to_string())))
|
||||
);
|
||||
assert_eq!(
|
||||
interpret("\"'one'\""),
|
||||
Ok(Some(Value::string("'one'".to_string())))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list() {
|
||||
assert_eq!(
|
||||
interpret("[1, 2, 'foobar']"),
|
||||
Ok(Some(Value::list(vec![
|
||||
Value::integer(1),
|
||||
Value::integer(2),
|
||||
Value::string("foobar".to_string()),
|
||||
])))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_list() {
|
||||
assert_eq!(interpret("[]"), Ok(Some(Value::list(Vec::new()))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map() {
|
||||
let mut map = BTreeMap::new();
|
||||
|
||||
map.insert(Identifier::new("x"), Value::integer(1));
|
||||
map.insert(Identifier::new("foo"), Value::string("bar".to_string()));
|
||||
|
||||
assert_eq!(
|
||||
interpret("{ x = 1, foo = 'bar' }"),
|
||||
Ok(Some(Value::map(map)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_map() {
|
||||
assert_eq!(interpret("{}"), Ok(Some(Value::map(BTreeMap::new()))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_types() {
|
||||
let mut map = BTreeMap::new();
|
||||
|
||||
map.insert(Identifier::new("x"), Value::integer(1));
|
||||
map.insert(Identifier::new("foo"), Value::string("bar".to_string()));
|
||||
|
||||
assert_eq!(
|
||||
interpret("{ x <int> = 1, foo <str> = 'bar' }"),
|
||||
Ok(Some(Value::map(map)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_type_errors() {
|
||||
assert_eq!(
|
||||
interpret("{ foo <bool> = 'bar' }"),
|
||||
Err(vec![Error::Validation {
|
||||
error: ValidationError::TypeCheck(TypeCheckError {
|
||||
actual: Type::String,
|
||||
expected: Type::Boolean
|
||||
}),
|
||||
span: (0..0).into()
|
||||
}])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn range() {
|
||||
assert_eq!(interpret("0..100"), Ok(Some(Value::range(0..100))));
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use dust_lang::{
|
||||
abstract_tree::Type,
|
||||
abstract_tree::{Expression, Identifier, Statement, Type},
|
||||
error::{Error, TypeCheckError, ValidationError},
|
||||
*,
|
||||
};
|
||||
@ -33,3 +33,15 @@ fn set_variable_with_type_error() {
|
||||
}])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_variable() {
|
||||
assert_eq!(
|
||||
interpret("foobar = (x: int): int x; foobar"),
|
||||
Ok(Some(Value::function(
|
||||
vec![(Identifier::new("x"), Type::Integer)],
|
||||
Type::Integer,
|
||||
Statement::Expression(Expression::Identifier(Identifier::new("x")))
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user