ruschm 0.2.0

Scheme(R7RS-small) interpretor/compiler rust implementation
Documentation
use ruschm::{
    error::ToLocated,
    error::{ErrorData, SchemeError},
    interpreter::{error::LogicError, Interpreter},
    list,
    parser::pair::GenericPair,
    values::Number,
    values::Pair,
    values::Type,
    values::Value,
};

#[test]
fn list() -> Result<(), SchemeError> {
    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
    assert_eq!(
        interpreter.eval("(list 1 2 3)".chars())?,
        Some(Value::Pair(Box::new(list!(
            Value::Number(Number::Integer(1)),
            Value::Number(Number::Integer(2)),
            Value::Number(Number::Integer(3))
        ))))
    );

    assert_eq!(
        interpreter.eval("'(1 2 . 3)".chars())?,
        Some(Value::Pair(Box::new(Pair::Some(
            Value::Number(Number::Integer(1)),
            Value::Pair(Box::new(Pair::Some(
                Value::Number(Number::Integer(2)),
                Value::Number(Number::Integer(3))
            )))
        ))))
    );

    assert_eq!(
        interpreter.eval("(car (list 1 2))".chars())?,
        Some(Value::Number(Number::Integer(1)))
    );

    assert_eq!(
        interpreter.eval("(cdr (list 1 2))".chars())?,
        Some(Value::Pair(Box::new(list!(Value::Number(
            Number::Integer(2)
        )))))
    );

    assert_eq!(
        interpreter.eval("(pair? (list 1 2))".chars())?,
        Some(Value::Boolean(true))
    );

    assert_eq!(
        interpreter.eval("(pair? '())".chars())?,
        Some(Value::Boolean(false))
    );
    assert_eq!(
        interpreter.eval("(pair? 1)".chars())?,
        Some(Value::Boolean(false))
    );
    Ok(())
}

#[test]
fn vector() -> Result<(), SchemeError> {
    use ruschm::values::ValueReference;
    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
    assert_eq!(
        interpreter.eval("(vector 1 2 3)".chars())?,
        Some(Value::Vector(ValueReference::new_mutable(vec![
            Value::Number(Number::Integer(1)),
            Value::Number(Number::Integer(2)),
            Value::Number(Number::Integer(3)),
        ])))
    );
    assert_eq!(
        interpreter.eval("(vector)".chars())?,
        Some(Value::Vector(ValueReference::new_mutable(vec![])))
    );
    Ok(())
}

#[test]
fn apply() -> Result<(), SchemeError> {
    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
    assert_eq!(
        interpreter.eval("(apply + 1 2 '(3 4))".chars())?,
        Some(Value::Number(Number::Integer(10)))
    );
    assert_eq!(
        interpreter.eval("(apply + 1)".chars()),
        Err(ErrorData::Logic(LogicError::TypeMisMatch("1".to_owned(), Type::Pair)).no_locate())
    );
    Ok(())
}

#[test]
fn booleans() -> Result<(), SchemeError> {
    {
        let mut interpreter = Interpreter::<f32>::new_with_stdlib();
        assert_eq!(
            interpreter.eval("(if #f #t #f)".chars())?,
            Some(Value::Boolean(false))
        );
        assert_eq!(
            interpreter.eval("(if #t #t #f)".chars())?,
            Some(Value::Boolean(true))
        );
        assert_eq!(
            interpreter.eval("(if '() #t #f)".chars())?,
            Some(Value::Boolean(true))
        );
        assert_eq!(
            interpreter.eval("(if 1 #t #f)".chars())?,
            Some(Value::Boolean(true))
        );
        assert_eq!(
            interpreter.eval("(if 0 #t #f)".chars())?,
            Some(Value::Boolean(true))
        );
    }

    {
        let mut interpreter = Interpreter::<f32>::new_with_stdlib();
        assert_eq!(
            interpreter.eval("(not #f)".chars())?,
            Some(Value::Boolean(true))
        );
        assert_eq!(
            interpreter.eval("(not #t)".chars())?,
            Some(Value::Boolean(false))
        );
        assert_eq!(
            interpreter.eval("(not '())".chars())?,
            Some(Value::Boolean(false))
        );
        assert_eq!(
            interpreter.eval("(not 1)".chars())?,
            Some(Value::Boolean(false))
        );
        assert_eq!(
            interpreter.eval("(not 0)".chars())?,
            Some(Value::Boolean(false))
        );
    }

    {
        let mut interpreter = Interpreter::<f32>::new_with_stdlib();
        assert_eq!(
            interpreter.eval("(boolean? #t)".chars())?,
            Some(Value::Boolean(true))
        );
        assert_eq!(
            interpreter.eval("(boolean? #f)".chars())?,
            Some(Value::Boolean(true))
        );
        assert_eq!(
            interpreter.eval("(boolean? '())".chars())?,
            Some(Value::Boolean(false))
        );
        assert_eq!(
            interpreter.eval("(boolean? 1)".chars())?,
            Some(Value::Boolean(false))
        );
        assert_eq!(
            interpreter.eval("(boolean? 0)".chars())?,
            Some(Value::Boolean(false))
        );
    }

    {
        let mut interpreter = Interpreter::<f32>::new_with_stdlib();
        assert_eq!(
            interpreter.eval("(boolean=? #t #t)".chars())?,
            Some(Value::Boolean(true))
        );
        assert_eq!(
            interpreter.eval("(boolean=? #f #f)".chars())?,
            Some(Value::Boolean(true))
        );
        assert_eq!(
            interpreter.eval("(boolean=? #f #t)".chars())?,
            Some(Value::Boolean(false))
        );
        assert_eq!(
            interpreter.eval("(boolean=? 1 1)".chars()),
            Err(
                ErrorData::Logic(LogicError::TypeMisMatch("1".to_string(), Type::Boolean))
                    .no_locate()
            )
        );
    }
    Ok(())
}