stackr-rs 0.1.14

A stack-based interpreter to be embedded in your application. Heavily inspired by Forth.
Documentation
use super::*;

pub fn register_builtins<State>(interpreter: &mut Interpreter<State>) {
    interpreter.register_builtin(
        "==",
        "any any -- 0|1",
        "Checks if two values are equal. Puts 1 on the stack if they are equal, 0 otherwise.",
        "1 1 ==",
        |interpreter| {
            let a = interpreter.pop()?;
            let b = interpreter.pop()?;
            if a == b {
                interpreter.push_number(1.0);
            } else {
                interpreter.push_number(0.0);
            }
            Ok(())
        },
    );

    interpreter.register_builtin(
        "!=",
        "any any -- 0|1",
        "Checks if two values are not equal. Puts 1 on the stack if they are not equal, 0 otherwise.",
        "1 2 !=",
        |interpreter| {
            let a = interpreter.pop()?;
            let b = interpreter.pop()?;
            if a != b {
                interpreter.push_number(1.0);
            } else {
                interpreter.push_number(0.0);
            }
            Ok(())
        },
    );

    interpreter.register_builtin(
        ">",
        "n n -- 0|1",
        "Checks if the second number is greater than the first. Puts 1 on the stack if it is, 0 otherwise.",
        "1 2 >",
        |interpreter| {
            let a = interpreter.pop_number()?;
            let b = interpreter.pop_number()?;
            if a > b {
                interpreter.push_number(1.0);
            } else {
                interpreter.push_number(0.0);
            }
            Ok(())
        },
    );

    interpreter.register_builtin(
        ">=",
        "n n -- 0|1",
        "Checks if the second number is greater than or equal to the first. Puts 1 on the stack if it is, 0 otherwise.",
        "1 2 >=",
        |interpreter| {
            let a = interpreter.pop_number()?;
            let b = interpreter.pop_number()?;
            if a >= b {
                interpreter.push_number(1.0);
            } else {
                interpreter.push_number(0.0);
            }
            Ok(())
        },
    );

    interpreter.register_builtin(
        "<",
        "n n -- 0|1",
        "Checks if the second number is less than the first. Puts 1 on the stack if it is, 0 otherwise.",
        "1 2 <",
        |interpreter| {
            let a = interpreter.pop_number()?;
            let b = interpreter.pop_number()?;
            if a < b {
                interpreter.push_number(1.0);
            } else {
                interpreter.push_number(0.0);
            }
            Ok(())
        },
    );

    interpreter.register_builtin(
        "<=",
        "n n -- 0|1",
        "Checks if the second number is less than or equal to the first. Puts 1 on the stack if it is, 0 otherwise.",
        "1 2 <=",
        |interpreter| {
            let a = interpreter.pop_number()?;
            let b = interpreter.pop_number()?;
            if a <= b {
                interpreter.push_number(1.0);
            } else {
                interpreter.push_number(0.0);
            }
            Ok(())
        },
    );
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_greater_than_equal_than_two_numbers_returns_1_if_greater_than() {
        let mut interpreter = Interpreter::new(());
        let code = "1 2 >=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_greater_than_equal_than_two_numbers_returns_1_if_equal() {
        let mut interpreter = Interpreter::new(());
        let code = "2 2 >=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_greater_than_equal_two_numbers_returns_0() {
        let mut interpreter = Interpreter::new(());
        let code = "5 2 >=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_less_equal_than_two_numbers_returns_1_if_less_than() {
        let mut interpreter = Interpreter::new(());
        let code = "2 1 <=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_less_equal_than_two_numbers_returns_1_if_equal() {
        let mut interpreter = Interpreter::new(());
        let code = "2 2 <=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_less_than_equal_two_numbers_returns_0() {
        let mut interpreter = Interpreter::new(());
        let code = "1 2 <=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_less_than_two_numbers_returns_1() {
        let mut interpreter = Interpreter::new(());
        let code = "2 1 <";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_less_than_two_numbers_returns_0() {
        let mut interpreter = Interpreter::new(());
        let code = "1 2 <";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_greater_than_two_numbers_returns_1() {
        let mut interpreter = Interpreter::new(());
        let code = "1 2 >";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_greater_than_two_numbers_returns_0() {
        let mut interpreter = Interpreter::new(());
        let code = "2 1 >";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_equal_two_numbers_returns_1() {
        let mut interpreter = Interpreter::new(());
        let code = "1 1 ==";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_equal_two_numbers_returns_0() {
        let mut interpreter = Interpreter::new(());
        let code = "1 -1 ==";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_equal_two_strings_returns_1() {
        let mut interpreter = Interpreter::new(());
        let code = "\"hello\" \"hello\" ==";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_equal_two_strings_returns_0() {
        let mut interpreter = Interpreter::new(());
        let code = "\"bob says\" \"hello\" ==";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_two_addresses_are_equal() {
        let mut interpreter = Interpreter::new(());
        let address = Address::new(1000);
        interpreter.push_address(address);
        interpreter.push_address(address);
        let code = "==";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_two_addresses_are_not_equal() {
        let mut interpreter = Interpreter::new(());
        interpreter.push_address(Address::new(1020));
        interpreter.push_address(Address::new(1000));
        let code = "==";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_equal_different_types_returns_0() {
        let mut interpreter = Interpreter::new(());
        interpreter.push_number(1.0);
        interpreter.push_string("hello".to_string());
        let code = "==";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());

        let mut interpreter = Interpreter::new(());
        interpreter.push_address(Address::new(1000));
        interpreter.push_string("hello".to_string());
        let code = "==";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_not_equal_two_numbers_returns_1() {
        let mut interpreter = Interpreter::new(());
        let code = "1 2 !=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_not_equal_two_numbers_returns_0() {
        let mut interpreter = Interpreter::new(());
        let code = "1 1 !=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_not_equal_two_strings_returns_1() {
        let mut interpreter = Interpreter::new(());
        let code = "\"bob says\" \"hello\" !=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_not_equal_two_strings_returns_0() {
        let mut interpreter = Interpreter::new(());
        let code = "\"hello\" \"hello\" !=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_not_equal_two_addresses_returns_1() {
        let mut interpreter = Interpreter::new(());
        interpreter.push_address(Address::new(1000));
        interpreter.push_address(Address::new(1030));
        let code = "!=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_not_equal_two_addresses_returns_0() {
        let mut interpreter = Interpreter::new(());
        interpreter.push_address(Address::new(1000));
        interpreter.push_address(Address::new(1000));
        let code = "!=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(0.0, interpreter.pop_number().unwrap());
    }

    #[test]
    fn test_not_equal_different_types_returns_1() {
        let mut interpreter = Interpreter::new(());
        interpreter.push_number(1.0);
        interpreter.push_string("hello".to_string());
        let code = "!=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());

        let mut interpreter = Interpreter::new(());
        interpreter.push_address(Address::new(1000));
        interpreter.push_string("hello".to_string());
        let code = "!=";
        let result = interpreter.evaluate(code, None);
        assert_eq!(result, Ok(()));
        assert_eq!(1.0, interpreter.pop_number().unwrap());
    }
}