uni_core/primitives/
fetch.rs

1// RUST CONCEPT: Forth-style variable fetch (@)
2// Fetches the value stored in a variable
3use crate::compat::format;
4use crate::interpreter::Interpreter;
5use crate::value::{RuntimeError, Value};
6
7// RUST CONCEPT: Fetch primitive (@)
8// Stack-based: ( var -- value )
9// Reads the value from a Variable
10pub fn fetch_builtin(interp: &mut Interpreter) -> Result<(), RuntimeError> {
11    let var = interp.pop()?;
12
13    match var {
14        Value::Variable(ref cell) => {
15            // Borrow the value from the RefCell and clone it
16            let value = cell.borrow().clone();
17            interp.push(value);
18            Ok(())
19        }
20        _ => Err(RuntimeError::TypeError(format!(
21            "@ expects Variable, got {:?}",
22            var
23        ))),
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30    use crate::compat::Rc;
31    use crate::value::Value;
32
33    #[cfg(not(target_os = "none"))]
34    use std::cell::RefCell;
35    #[cfg(target_os = "none")]
36    use core::cell::RefCell;
37
38    fn setup_interpreter() -> Interpreter {
39        Interpreter::new()
40    }
41
42    #[test]
43    fn test_fetch_basic() {
44        let mut interp = setup_interpreter();
45
46        // Create a variable containing 42
47        let var = Value::Variable(Rc::new(RefCell::new(Value::Int32(42))));
48        interp.push(var);
49
50        // Fetch the value
51        fetch_builtin(&mut interp).unwrap();
52
53        // Check result
54        let result = interp.pop().unwrap();
55        assert!(matches!(result, Value::Int32(42)));
56    }
57
58    #[test]
59    fn test_fetch_wrong_type() {
60        let mut interp = setup_interpreter();
61
62        // Try to fetch from non-variable
63        interp.push(Value::Int32(42));
64        let result = fetch_builtin(&mut interp);
65
66        assert!(matches!(result, Err(RuntimeError::TypeError(_))));
67    }
68
69    #[test]
70    fn test_fetch_stack_underflow() {
71        let mut interp = setup_interpreter();
72
73        let result = fetch_builtin(&mut interp);
74        assert!(matches!(result, Err(RuntimeError::StackUnderflow)));
75    }
76
77    #[test]
78    fn test_fetch_different_types() {
79        let mut interp = setup_interpreter();
80
81        // Test with string
82        let var = Value::Variable(Rc::new(RefCell::new(Value::String(Rc::from("hello")))));
83        interp.push(var);
84        fetch_builtin(&mut interp).unwrap();
85
86        let result = interp.pop().unwrap();
87        if let Value::String(s) = result {
88            assert_eq!(&*s, "hello");
89        } else {
90            panic!("Expected String");
91        }
92
93        // Test with boolean
94        let var = Value::Variable(Rc::new(RefCell::new(Value::Boolean(true))));
95        interp.push(var);
96        fetch_builtin(&mut interp).unwrap();
97
98        let result = interp.pop().unwrap();
99        assert!(matches!(result, Value::Boolean(true)));
100    }
101}