Skip to main content

neutron_engine/iris/
value.rs

1use std::collections::HashMap;
2use std::fmt;
3use std::rc::Rc;
4use std::cell::RefCell;
5
6/// Iris Value Types
7#[derive(Debug, Clone)]
8pub enum Value {
9    Null,
10    Bool(bool),
11    Number(f64),
12    String(String),
13    Array(Rc<RefCell<Vec<Value>>>),
14    Object(Rc<RefCell<HashMap<String, Value>>>),
15    Function {
16        params: Vec<String>,
17        body: Vec<crate::iris::parser::Stmt>,
18        closure: Rc<RefCell<HashMap<String, Value>>>,
19    },
20    Builtin(fn(&[Value]) -> Result<Value, String>),
21    Return(Box<Value>),
22}
23
24impl PartialEq for Value {
25    fn eq(&self, other: &Self) -> bool {
26        match (self, other) {
27            (Value::Null, Value::Null) => true,
28            (Value::Bool(a), Value::Bool(b)) => a == b,
29            (Value::Number(a), Value::Number(b)) => a == b,
30            (Value::String(a), Value::String(b)) => a == b,
31            (Value::Array(a), Value::Array(b)) => a == b,
32            (Value::Object(a), Value::Object(b)) => a == b,
33            (
34                Value::Function { params: ap, body: ab, closure: ac },
35                Value::Function { params: bp, body: bb, closure: bc },
36            ) => ap == bp && ab == bb && ac == bc,
37            (Value::Builtin(a), Value::Builtin(b)) => std::ptr::fn_addr_eq(*a, *b),
38            (Value::Return(a), Value::Return(b)) => a == b,
39            _ => false,
40        }
41    }
42}
43
44impl fmt::Display for Value {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match self {
47            Value::Null => write!(f, "null"),
48            Value::Bool(b) => write!(f, "{}", b),
49            Value::Number(n) => {
50                if n.fract() == 0.0 {
51                    write!(f, "{:.0}", n)
52                } else {
53                    write!(f, "{}", n)
54                }
55            }
56            Value::String(s) => write!(f, "{}", s),
57            Value::Array(arr) => {
58                let arr = arr.borrow();
59                let items: Vec<String> = arr.iter().map(|v| v.to_string()).collect();
60                write!(f, "[{}]", items.join(", "))
61            }
62            Value::Object(obj) => {
63                let obj = obj.borrow();
64                let items: Vec<String> = obj
65                    .iter()
66                    .map(|(k, v)| format!("{}: {}", k, v))
67                    .collect();
68                write!(f, "{{{}}}", items.join(", "))
69            }
70            Value::Function { .. } => write!(f, "<function>"),
71            Value::Builtin(_) => write!(f, "<builtin function>"),
72            Value::Return(v) => write!(f, "{}", v),
73        }
74    }
75}
76
77impl Value {
78    pub fn is_truthy(&self) -> bool {
79        match self {
80            Value::Null => false,
81            Value::Bool(b) => *b,
82            Value::Number(n) => *n != 0.0,
83            Value::String(s) => !s.is_empty(),
84            _ => true,
85        }
86    }
87
88    pub fn type_name(&self) -> &'static str {
89        match self {
90            Value::Null => "null",
91            Value::Bool(_) => "bool",
92            Value::Number(_) => "number",
93            Value::String(_) => "string",
94            Value::Array(_) => "array",
95            Value::Object(_) => "object",
96            Value::Function { .. } | Value::Builtin(_) => "function",
97            Value::Return(_) => "return",
98        }
99    }
100}
101