uni_core/primitives/
less_equal.rs

1use crate::compat::format;
2use crate::interpreter::Interpreter;
3use crate::primitives::numeric_promotion::promote_pair;
4use crate::value::{RuntimeError, Value};
5
6pub fn less_equal_builtin(interp: &mut Interpreter) -> Result<(), RuntimeError> {
7    let b = interp.pop()?;
8    let a = interp.pop()?;
9
10    // Promote to common type for comparison
11    let (pa, pb) = promote_pair(&a, &b);
12
13    let result = match (&pa, &pb) {
14        (Value::Int32(i1), Value::Int32(i2)) => i1 <= i2,
15        (Value::Integer(i1), Value::Integer(i2)) => i1 <= i2,
16        (Value::Rational(r1), Value::Rational(r2)) => r1 <= r2,
17        (Value::Number(n1), Value::Number(n2)) => n1 <= n2,
18        _ => {
19            return Err(RuntimeError::TypeError(format!(
20                "Cannot compare {:?} and {:?}",
21                a, b
22            )))
23        }
24    };
25
26    interp.push(Value::Boolean(result));
27    Ok(())
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33    use crate::value::Value;
34
35    fn setup_interpreter() -> Interpreter {
36        Interpreter::new()
37    }
38
39    #[test]
40    fn test_less_equal_true_less() {
41        let mut interp = setup_interpreter();
42        interp.push(Value::Number(3.0));
43        interp.push(Value::Number(5.0));
44
45        less_equal_builtin(&mut interp).unwrap();
46
47        let result = interp.pop().unwrap();
48        assert!(matches!(result, Value::Boolean(true)));
49    }
50
51    #[test]
52    fn test_less_equal_true_equal() {
53        let mut interp = setup_interpreter();
54        interp.push(Value::Number(5.0));
55        interp.push(Value::Number(5.0));
56
57        less_equal_builtin(&mut interp).unwrap();
58
59        let result = interp.pop().unwrap();
60        assert!(matches!(result, Value::Boolean(true)));
61    }
62
63    #[test]
64    fn test_less_equal_false() {
65        let mut interp = setup_interpreter();
66        interp.push(Value::Number(7.0));
67        interp.push(Value::Number(3.0));
68
69        less_equal_builtin(&mut interp).unwrap();
70
71        let result = interp.pop().unwrap();
72        assert!(matches!(result, Value::Boolean(false)));
73    }
74
75    #[test]
76    fn test_less_equal_negative_numbers() {
77        let mut interp = setup_interpreter();
78        interp.push(Value::Number(-10.0));
79        interp.push(Value::Number(-10.0));
80
81        less_equal_builtin(&mut interp).unwrap();
82
83        let result = interp.pop().unwrap();
84        assert!(matches!(result, Value::Boolean(true)));
85    }
86
87    #[test]
88    fn test_less_equal_stack_underflow() {
89        let mut interp = setup_interpreter();
90
91        let result = less_equal_builtin(&mut interp);
92        assert!(matches!(result, Err(RuntimeError::StackUnderflow)));
93
94        interp.push(Value::Number(1.0));
95        let result = less_equal_builtin(&mut interp);
96        assert!(matches!(result, Err(RuntimeError::StackUnderflow)));
97    }
98
99    #[test]
100    fn test_less_equal_type_error() {
101        let mut interp = setup_interpreter();
102        interp.push(Value::String("hello".into()));
103        interp.push(Value::Number(5.0));
104
105        let result = less_equal_builtin(&mut interp);
106        assert!(matches!(result, Err(RuntimeError::TypeError(_))));
107    }
108}