xmachine/
value.rs

1use crate::{Function, Machine, Ref};
2use core::ops::{Add, Div, Mul, Not, Rem, Sub};
3
4// We need BTreeMap to implement the Tree type
5use alloc::collections::BTreeMap;
6// For ToString generics
7use alloc::string::{String, ToString};
8// We need Vec for dynamically allocated lists
9use alloc::vec::Vec;
10// For implementing Display and Debug
11use core::fmt::{Debug, Display, Error, Formatter};
12
13#[derive(Clone, PartialEq, PartialOrd)]
14pub enum Value {
15    String(String),
16    Number(f64),
17    List(Vec<Ref<Self>>),
18    Tree(BTreeMap<String, Ref<Self>>),
19    Function(Function<Machine, (), Machine>),
20    Error(String),
21    None,
22}
23
24impl Value {
25    /// Creates a new reference to a Number
26    pub fn number<N: Into<f64>>(n: N) -> Ref<Self> {
27        Ref::new(Self::Number(n.into()))
28    }
29
30    /// Creates a new reference to a String
31    pub fn string<S: ToString>(s: S) -> Ref<Self> {
32        Ref::new(Self::String(s.to_string()))
33    }
34
35    /// Creates a new reference to an empty List
36    pub fn list() -> Ref<Self> {
37        Ref::new(Self::List(Vec::new()))
38    }
39
40    /// Creates a new reference to an empty Tree
41    pub fn tree() -> Ref<Self> {
42        Ref::new(Self::Tree(BTreeMap::new()))
43    }
44
45    /// Creates a reference to a Function with a captured context, basically a Closure
46    pub fn function(f: impl 'static + Fn(&mut Machine) -> (), context: &Machine) -> Ref<Self> {
47        Ref::new(Self::Function(Function::new(
48            f,
49            context.clone().duplicate(),
50        )))
51    }
52
53    /// Creates a reference to an Error value
54    pub fn error<S: ToString>(s: S) -> Ref<Self> {
55        Ref::new(Self::Error(s.to_string()))
56    }
57
58    /// Creates a reference to an None value
59    pub fn none() -> Ref<Self> {
60        Ref::new(Self::None)
61    }
62
63    /// Copies the contents of this value
64    pub fn copy(&self) -> Ref<Self> {
65        // In the future, if memory leaks become a problem,
66        // we could try replacing the item clone with an
67        // item copy.
68        // This would recursively call copy to ensure no
69        // Refs are the same. It might be that we never
70        // need to change this, though.
71        match self {
72            Self::List(l) => {
73                let mut list = vec![];
74                for item in l {
75                    list.push(item.copy());
76                }
77                Ref::new(Self::List(list))
78            }
79            Self::Tree(l) => {
80                let mut map = BTreeMap::new();
81                for (name, item) in l {
82                    map.insert(name.clone(), item.copy());
83                }
84                Ref::new(Self::Tree(map))
85            }
86            _ => Ref::new(self.clone()),
87        }
88    }
89
90    /// Call this function in the context of the Machine
91    /// captured when this instance of the function was created
92    pub fn call(&self, machine: &mut Machine) {
93        if let Self::Function(f) = self {
94            // Get the captured machine back from the function
95            let mut temp_machine = f.get_context().clone();
96            // Give it the current machine's stack
97            temp_machine.stack = machine.stack.clone();
98            // Call the function with the new machine
99            f.call(&mut temp_machine);
100            // Give back the modified stack
101            machine.stack = temp_machine.stack;
102        }
103    }
104
105    /// Call this function in the context of the current machine,
106    /// meaning, execute the instructions of this function as if
107    /// they were not in a function.
108    pub fn call_global(&self, machine: &mut Machine) {
109        if let Self::Function(f) = self {
110            // Call the function with the given machine
111            f.call(machine);
112        }
113    }
114
115    pub fn is_err(&self) -> bool {
116        match self {
117            Self::Error(_) => true,
118            _ => false,
119        }
120    }
121
122    /// Return a reference to a value contained within a collection
123    pub fn index<S: ToString>(&mut self, s: S) -> Ref<Self> {
124        let key = s.to_string();
125        match self {
126            Self::String(s) => {
127                match key.parse::<usize>() {
128                    Ok(n) => {
129                        if s.len() > n {
130                            Value::string(s.chars().nth(n).unwrap().to_string())
131                        } else {
132                            Self::error("String index out of bounds")
133                        }
134                    }
135                    Err(_) => Self::error("Can't index string with non-integer"),
136                }
137            }
138            Self::Tree(t) => {
139                // If the current tree does not have a
140                // key with this name, create one
141                if !t.contains_key(&key) {
142                    t.insert(key.clone(), Self::none());
143                }
144
145                // Return a reference to this object in the table
146                Ref::clone(t.get(&key).unwrap())
147            }
148            Self::List(l) => {
149                // Convert to usize to index this value as a list
150                match key.parse::<usize>() {
151                    Ok(n) => {
152                        // If the requested index is too high, allocate space for it and continue
153                        if n >= l.len() {
154                            // Reserve space for new size
155                            // This is good because it minimizes the
156                            // number of numerous, small allocations.
157                            l.reserve(n - l.len() + 1);
158
159                            // Fill the space with None
160                            for _ in l.len()..=n {
161                                l.push(Self::none());
162                            }
163                        }
164
165                        // Return reference to the requested item in the list
166                        Ref::clone(&l[n])
167                    }
168                    // Could not convert key to usize
169                    Err(_) => Self::error("Can't index list with non-integer"),
170                }
171            }
172            // Tried to index something other than list or tree
173            _ => Self::error("Can't index non-list or non-tree"),
174        }
175    }
176}
177
178/// This implementation is a hack for implementing Display for Value
179impl Debug for Value {
180    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
181        write!(f, "{}", self)
182    }
183}
184
185/// How to display value
186impl Display for Value {
187    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
188        match self {
189            Self::String(s) => write!(f, "{}", s),
190            Self::Number(n) => write!(f, "{}", n),
191            Self::List(l) => write!(f, "{:?}", l), // Requires the dummy debug implementation above
192            Self::Tree(t) => write!(f, "{:?}", t), // Requires the dummy debug implementation above
193            Self::Function(func) => write!(f, "{}", func),
194            Self::Error(s) => write!(f, "<Exception: '{}'>", s),
195            Self::None => write!(f, "None"),
196        }
197    }
198}
199
200/// ############################################################
201/// The following traits are for implementing foreign functions!
202/// ############################################################
203
204/// Convert Value into a bool
205impl From<Value> for bool {
206    fn from(v: Value) -> Self {
207        match v {
208            Value::String(s) => s != "", // self != ""
209            Value::Number(n) => (if n < 0.0 { -n } else { n }) > 0.000_000_000_1, // self is non-zero
210            Value::List(l) => !l.is_empty(),                                      // self is not []
211            Value::Tree(t) => !t.is_empty(),                                      // self is not {}
212            Value::Function(_) => true, // functions are true values
213            Value::Error(_) => false,   // errors are false values
214            Value::None => false,       // nones are false values
215        }
216    }
217}
218
219/// Get a function from the value
220impl From<Value> for String {
221    fn from(v: Value) -> Self {
222        match v {
223            Value::String(s) => s,
224            Value::Error(e) => e,
225            _ => String::from(""),
226        }
227    }
228}
229
230/// Get a function from the value
231impl From<Value> for Function<Machine, (), Machine> {
232    fn from(v: Value) -> Self {
233        match v {
234            Value::Function(f) => f,
235            _ => Function::new(|_: &mut Machine| {}, Machine::new()),
236        }
237    }
238}
239
240/// Convert Value to unwrapped List
241impl From<Value> for Vec<Ref<Value>> {
242    fn from(v: Value) -> Self {
243        match v {
244            Value::List(l) => l,
245            _ => Vec::new(),
246        }
247    }
248}
249
250/// Convert Value to unwrapped Tree
251impl From<Value> for BTreeMap<String, Ref<Value>> {
252    fn from(v: Value) -> Self {
253        match v {
254            Value::Tree(t) => t,
255            _ => BTreeMap::new(),
256        }
257    }
258}
259
260/// Convert to floating point value
261impl From<Value> for f64 {
262    fn from(v: Value) -> Self {
263        match v {
264            Value::Number(n) => n,
265            _ => 0.0,
266        }
267    }
268}
269
270/// Convert to integer value
271impl From<Value> for i32 {
272    fn from(v: Value) -> Self {
273        match v {
274            Value::Number(n) => n as i32,
275            _ => 0,
276        }
277    }
278}
279
280/// Make Value from String
281impl From<String> for Value {
282    fn from(s: String) -> Self {
283        Value::String(s)
284    }
285}
286
287/// Make Value from &str
288impl From<&str> for Value {
289    fn from(s: &str) -> Self {
290        Value::String(s.to_string())
291    }
292}
293
294/// Make Value from bool
295impl From<bool> for Value {
296    fn from(n: bool) -> Self {
297        Value::Number(f64::from(n as i32))
298    }
299}
300
301/// Make Value from Number
302impl From<f64> for Value {
303    fn from(n: f64) -> Self {
304        Value::Number(n)
305    }
306}
307
308/// Make Value from Number
309impl From<i32> for Value {
310    fn from(n: i32) -> Self {
311        Value::Number(f64::from(n))
312    }
313}
314
315/// Make Value from List
316impl From<Vec<Ref<Value>>> for Value {
317    fn from(l: Vec<Ref<Value>>) -> Self {
318        Value::List(l)
319    }
320}
321
322/// Make Value from Tree
323impl From<BTreeMap<String, Ref<Value>>> for Value {
324    fn from(t: BTreeMap<String, Ref<Value>>) -> Self {
325        Value::Tree(t)
326    }
327}
328
329/// Make Value from Function
330impl From<Function<Machine, (), Machine>> for Value {
331    fn from(f: Function<Machine, (), Machine>) -> Self {
332        Value::Function(f)
333    }
334}
335
336/// ##############################################################
337/// The following traits are for implementing operators and logic!
338/// ##############################################################
339
340/// Add two values
341impl Add<Value> for Value {
342    type Output = Value;
343    fn add(self, rhs: Self) -> Self::Output {
344        match (self, rhs) {
345            // Concat two strings
346            (Self::String(s1), Self::String(s2)) => Self::String(s1 + &s2),
347            // Add two numbers
348            (Self::Number(m), Self::Number(n)) => Self::Number(m + n),
349            // Concat two lists
350            (Self::List(mut l1), Self::List(l2)) => {
351                l1.extend(l2);
352                Self::List(l1)
353            }
354            // Otherwise, return exception
355            (a, b) => Self::Error(format!("Could not add {} and {}", a, b)),
356        }
357    }
358}
359
360/// Subtract two values
361impl Sub<Value> for Value {
362    type Output = Value;
363    fn sub(self, rhs: Self) -> Self::Output {
364        match (self, rhs) {
365            // Subtract two numbers
366            (Self::Number(m), Self::Number(n)) => Self::Number(m - n),
367            // Otherwise, return exception
368            (a, b) => Self::Error(format!("Could not subtract {} and {}", a, b)),
369        }
370    }
371}
372
373/// Multiply two values
374impl Mul<Value> for Value {
375    type Output = Value;
376    fn mul(self, rhs: Self) -> Self::Output {
377        match (self, rhs) {
378            // Repeat a string
379            (Self::String(s1), Self::Number(n)) => Self::String(s1.repeat(n as usize)),
380            // Multiply two numbers
381            (Self::Number(m), Self::Number(n)) => Self::Number(m * n),
382            // Otherwise, return exception
383            (a, b) => Self::Error(format!("Could not multiply {} and {}", a, b)),
384        }
385    }
386}
387
388/// Divide two values
389impl Div<Value> for Value {
390    type Output = Value;
391    fn div(self, rhs: Self) -> Self::Output {
392        match (self, rhs) {
393            // Divide two numbers
394            (Self::Number(m), Self::Number(n)) => Self::Number(m / n),
395            // Otherwise, return exception
396            (a, b) => Self::Error(format!("Could not divide {} and {}", a, b)),
397        }
398    }
399}
400
401/// Remainder of two values
402impl Rem<Value> for Value {
403    type Output = Value;
404    fn rem(self, rhs: Self) -> Self::Output {
405        match (self, rhs) {
406            // Remainder of two numbers
407            (Self::Number(m), Self::Number(n)) => Self::Number(m % n),
408            // Otherwise, return exception
409            (a, b) => Self::Error(format!("Could not find the remainder of {} and {}", a, b)),
410        }
411    }
412}
413
414/// Negate value
415impl Not for Value {
416    type Output = Value;
417    fn not(self) -> Self::Output {
418        match self {
419            // Negate number
420            Self::Number(n) => match n as i32 {
421                // If number is zero, return true
422                0 => Self::Number(1.0),
423                // If number is not zero, return false
424                _ => Self::Number(0.0),
425            },
426            a => Self::Error(format!("Could not negate {}", a)),
427        }
428    }
429}
430
431/// Convert Value into Iter
432impl IntoIterator for Value {
433    type Item = Ref<Value>;
434    type IntoIter = alloc::vec::IntoIter<Self::Item>;
435
436    fn into_iter(self) -> Self::IntoIter {
437        match self {
438            Self::List(l) => l.into_iter(),
439            Self::String(s) => {
440                let mut result = vec![];
441                for ch in s.chars() {
442                    result.push(Self::string(ch.to_string()));
443                }
444                result.into_iter()
445            },
446            _ => vec![].into_iter()
447        }
448    }
449}