uni_core/primitives/
bit_and.rs

1use crate::interpreter::Interpreter;
2use crate::value::{RuntimeError, Value};
3
4pub fn bit_and_builtin(interp: &mut Interpreter) -> Result<(), RuntimeError> {
5    let b = interp.pop_number()?;
6    let a = interp.pop_number()?;
7
8    // Convert to integers for bitwise operations
9    let a_int = a as i64;
10    let b_int = b as i64;
11
12    let result = a_int & b_int;
13    interp.push(Value::Number(result as f64));
14    Ok(())
15}
16
17#[cfg(test)]
18mod tests {
19    use super::*;
20    use crate::value::Value;
21
22    fn setup_interpreter() -> Interpreter {
23        Interpreter::new()
24    }
25
26    #[test]
27    fn test_bit_and_basic() {
28        let mut interp = setup_interpreter();
29        interp.push(Value::Number(5.0)); // 101 in binary
30        interp.push(Value::Number(3.0)); // 011 in binary
31
32        bit_and_builtin(&mut interp).unwrap();
33
34        let result = interp.pop().unwrap();
35        assert!(matches!(result, Value::Number(n) if n == 1.0)); // 001 in binary
36    }
37
38    #[test]
39    fn test_bit_and_all_ones() {
40        let mut interp = setup_interpreter();
41        interp.push(Value::Number(15.0)); // 1111 in binary
42        interp.push(Value::Number(7.0)); // 0111 in binary
43
44        bit_and_builtin(&mut interp).unwrap();
45
46        let result = interp.pop().unwrap();
47        assert!(matches!(result, Value::Number(n) if n == 7.0)); // 0111 in binary
48    }
49
50    #[test]
51    fn test_bit_and_zero() {
52        let mut interp = setup_interpreter();
53        interp.push(Value::Number(255.0));
54        interp.push(Value::Number(0.0));
55
56        bit_and_builtin(&mut interp).unwrap();
57
58        let result = interp.pop().unwrap();
59        assert!(matches!(result, Value::Number(n) if n == 0.0));
60    }
61
62    #[test]
63    fn test_bit_and_same_values() {
64        let mut interp = setup_interpreter();
65        interp.push(Value::Number(42.0));
66        interp.push(Value::Number(42.0));
67
68        bit_and_builtin(&mut interp).unwrap();
69
70        let result = interp.pop().unwrap();
71        assert!(matches!(result, Value::Number(n) if n == 42.0));
72    }
73
74    #[test]
75    fn test_bit_and_powers_of_two() {
76        let mut interp = setup_interpreter();
77
78        let test_cases = [
79            (8.0, 4.0, 0.0),   // 1000 & 0100 = 0000
80            (12.0, 10.0, 8.0), // 1100 & 1010 = 1000
81            (7.0, 7.0, 7.0),   // 0111 & 0111 = 0111
82        ];
83
84        for (a, b, expected) in test_cases {
85            interp.push(Value::Number(a));
86            interp.push(Value::Number(b));
87            bit_and_builtin(&mut interp).unwrap();
88            let result = interp.pop().unwrap();
89            assert!(
90                matches!(result, Value::Number(n) if n == expected),
91                "{} & {} should be {}, got {:?}",
92                a,
93                b,
94                expected,
95                result
96            );
97        }
98    }
99
100    #[test]
101    fn test_bit_and_large_numbers() {
102        let mut interp = setup_interpreter();
103        interp.push(Value::Number(1023.0)); // 1111111111 in binary (10 bits)
104        interp.push(Value::Number(512.0)); // 1000000000 in binary
105
106        bit_and_builtin(&mut interp).unwrap();
107
108        let result = interp.pop().unwrap();
109        assert!(matches!(result, Value::Number(n) if n == 512.0));
110    }
111
112    #[test]
113    fn test_bit_and_negative_numbers() {
114        let mut interp = setup_interpreter();
115
116        // Test with negative numbers (two's complement)
117        interp.push(Value::Number(-1.0));
118        interp.push(Value::Number(7.0));
119
120        bit_and_builtin(&mut interp).unwrap();
121
122        let result = interp.pop().unwrap();
123        assert!(matches!(result, Value::Number(n) if n == 7.0)); // -1 has all bits set
124    }
125
126    #[test]
127    fn test_bit_and_fractional_truncation() {
128        let mut interp = setup_interpreter();
129
130        // Fractional parts should be truncated
131        interp.push(Value::Number(5.7));
132        interp.push(Value::Number(3.9));
133
134        bit_and_builtin(&mut interp).unwrap();
135
136        let result = interp.pop().unwrap();
137        assert!(matches!(result, Value::Number(n) if n == 1.0)); // 5 & 3 = 1
138    }
139
140    #[test]
141    fn test_bit_and_identity_mask() {
142        let mut interp = setup_interpreter();
143
144        // Test common bit masks
145        let value = 170.0; // 10101010 in binary
146        interp.push(Value::Number(value));
147        interp.push(Value::Number(255.0)); // 11111111 in binary
148
149        bit_and_builtin(&mut interp).unwrap();
150
151        let result = interp.pop().unwrap();
152        assert!(matches!(result, Value::Number(n) if n == value)); // Should be unchanged
153    }
154
155    #[test]
156    fn test_bit_and_alternating_pattern() {
157        let mut interp = setup_interpreter();
158        interp.push(Value::Number(170.0)); // 10101010 in binary
159        interp.push(Value::Number(85.0)); // 01010101 in binary
160
161        bit_and_builtin(&mut interp).unwrap();
162
163        let result = interp.pop().unwrap();
164        assert!(matches!(result, Value::Number(n) if n == 0.0)); // No common bits
165    }
166
167    #[test]
168    fn test_bit_and_stack_underflow() {
169        let mut interp = setup_interpreter();
170
171        let result = bit_and_builtin(&mut interp);
172        assert!(matches!(result, Err(RuntimeError::StackUnderflow)));
173
174        interp.push(Value::Number(5.0));
175        let result = bit_and_builtin(&mut interp);
176        assert!(matches!(result, Err(RuntimeError::StackUnderflow)));
177    }
178
179    #[test]
180    fn test_bit_and_type_error() {
181        let mut interp = setup_interpreter();
182        interp.push(Value::String("hello".into()));
183        interp.push(Value::Number(5.0));
184
185        let result = bit_and_builtin(&mut interp);
186        assert!(matches!(result, Err(RuntimeError::TypeError(_))));
187    }
188}