uni_core/primitives/
var.rs1use crate::compat::{format, Rc};
4use crate::interpreter::Interpreter;
5use crate::value::{RuntimeError, Value};
6
7#[cfg(not(target_os = "none"))]
8use std::cell::RefCell;
9#[cfg(target_os = "none")]
10use core::cell::RefCell;
11
12pub fn var_builtin(interp: &mut Interpreter) -> Result<(), RuntimeError> {
16 let name_val = interp.pop()?;
17 let initial_value = interp.pop()?;
18
19 let name = match name_val {
21 Value::Atom(ref atom) => atom.clone(),
22 _ => {
23 return Err(RuntimeError::TypeError(format!(
24 "var expects atom name, got {:?}",
25 name_val
26 )))
27 }
28 };
29
30 let var = Value::Variable(Rc::new(RefCell::new(initial_value)));
32
33 let dict_entry = crate::interpreter::DictEntry {
35 value: var,
36 is_executable: true,
37 doc: None,
38 };
39
40 interp.dictionary.insert(name, dict_entry);
41
42 Ok(())
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use crate::value::Value;
49
50 fn setup_interpreter() -> Interpreter {
51 Interpreter::new()
52 }
53
54 #[test]
55 fn test_var_basic() {
56 let mut interp = setup_interpreter();
57
58 interp.push(Value::Int32(42));
60 let name_atom = interp.intern_atom("x");
61 interp.push(Value::Atom(name_atom.clone()));
62 var_builtin(&mut interp).unwrap();
63
64 assert!(interp.dictionary.contains_key(&name_atom));
66
67 let entry = interp.dictionary.get(&name_atom).unwrap();
69
70 assert!(matches!(entry.value, Value::Variable(_)));
72
73 assert!(entry.is_executable);
75 }
76
77 #[test]
78 fn test_var_wrong_name_type() {
79 let mut interp = setup_interpreter();
80
81 interp.push(Value::Int32(42));
83 interp.push(Value::Int32(5)); let result = var_builtin(&mut interp);
85
86 assert!(matches!(result, Err(RuntimeError::TypeError(_))));
87 }
88
89 #[test]
90 fn test_var_stack_underflow() {
91 let mut interp = setup_interpreter();
92
93 let result = var_builtin(&mut interp);
95 assert!(matches!(result, Err(RuntimeError::StackUnderflow)));
96 }
97}