rigz_vm/value/
mod.rs

1mod add;
2mod bitand;
3mod bitor;
4mod bitxor;
5mod div;
6mod error;
7mod logical;
8mod mul;
9mod neg;
10mod not;
11mod rem;
12mod reverse;
13mod shl;
14mod shr;
15mod sub;
16
17pub use error::VMError;
18use std::cell::RefCell;
19
20use crate::{impl_from, Number, RigzType, ValueRange};
21use indexmap::IndexMap;
22use serde::{Deserialize, Serialize};
23use std::cmp::Ordering;
24use std::fmt::{Display, Formatter};
25use std::hash::{Hash, Hasher};
26use std::rc::Rc;
27
28#[derive(Clone, Debug, Default, Serialize, Deserialize)]
29#[serde(untagged)]
30pub enum Value {
31    #[default]
32    None,
33    Bool(bool),
34    Number(Number),
35    String(String),
36    // todo Lists, Maps, & Tuples should use Rc<RefCell<Value>> to make this language fully pass by reference
37    List(Vec<Value>),
38    Map(IndexMap<Value, Value>),
39    Range(ValueRange),
40    Error(VMError),
41    Tuple(Vec<Value>),
42    // todo create dedicated object value to avoid map usage everywhere, might need to be a trait. Create to_o method for value
43    Type(RigzType),
44}
45
46impl From<Value> for Rc<RefCell<Value>> {
47    #[inline]
48    fn from(value: Value) -> Self {
49        Rc::new(RefCell::new(value))
50    }
51}
52
53impl_from! {
54    bool, Value, Value::Bool;
55    String, Value, Value::String;
56    VMError, Value, Value::Error;
57    ValueRange, Value, Value::Range;
58    RigzType, Value, Value::Type;
59}
60
61impl From<&'_ str> for Value {
62    #[inline]
63    fn from(value: &'_ str) -> Self {
64        Value::String(value.to_string())
65    }
66}
67
68impl<T: Into<Number>> From<T> for Value {
69    #[inline]
70    fn from(value: T) -> Self {
71        Value::Number(value.into())
72    }
73}
74
75impl<T: Into<Value>> From<Vec<T>> for Value {
76    #[inline]
77    fn from(value: Vec<T>) -> Self {
78        Value::List(value.into_iter().map(|v| v.into()).collect())
79    }
80}
81
82impl<K: Into<Value>, V: Into<Value>> From<IndexMap<K, V>> for Value {
83    #[inline]
84    fn from(value: IndexMap<K, V>) -> Self {
85        Value::Map(
86            value
87                .into_iter()
88                .map(|(k, v)| (k.into(), v.into()))
89                .collect(),
90        )
91    }
92}
93
94impl From<()> for Value {
95    #[inline]
96    fn from(_value: ()) -> Self {
97        Value::None
98    }
99}
100
101impl<A: Into<Value>, B: Into<Value>> From<(A, B)> for Value {
102    #[inline]
103    fn from(value: (A, B)) -> Self {
104        Value::Tuple(vec![value.0.into(), value.1.into()])
105    }
106}
107
108impl<A: Into<Value>, B: Into<Value>, C: Into<Value>> From<(A, B, C)> for Value {
109    #[inline]
110    fn from(value: (A, B, C)) -> Self {
111        Value::Tuple(vec![value.0.into(), value.1.into(), value.2.into()])
112    }
113}
114
115impl<A: Into<Value>, B: Into<Value>, C: Into<Value>, D: Into<Value>> From<(A, B, C, D)> for Value {
116    #[inline]
117    fn from(value: (A, B, C, D)) -> Self {
118        Value::Tuple(vec![
119            value.0.into(),
120            value.1.into(),
121            value.2.into(),
122            value.3.into(),
123        ])
124    }
125}
126
127impl<A: Into<Value>, B: Into<Value>, C: Into<Value>, D: Into<Value>, E: Into<Value>>
128    From<(A, B, C, D, E)> for Value
129{
130    #[inline]
131    fn from(value: (A, B, C, D, E)) -> Self {
132        Value::Tuple(vec![
133            value.0.into(),
134            value.1.into(),
135            value.2.into(),
136            value.3.into(),
137            value.4.into(),
138        ])
139    }
140}
141
142impl<V: Into<Value>> From<Option<V>> for Value {
143    #[inline]
144    fn from(value: Option<V>) -> Self {
145        match value {
146            None => Value::None,
147            Some(v) => v.into(),
148        }
149    }
150}
151
152impl<V: Into<Value>> From<Result<V, VMError>> for Value {
153    #[inline]
154    fn from(value: Result<V, VMError>) -> Self {
155        match value {
156            Ok(v) => v.into(),
157            Err(e) => e.into(),
158        }
159    }
160}
161
162impl Eq for Value {}
163
164impl PartialOrd for Value {
165    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
166        if self.eq(other) {
167            return Some(Ordering::Equal);
168        }
169
170        match (self, other) {
171            // todo some of these should probably use None?
172            (Value::Error(_), _) => Some(Ordering::Less),
173            (_, Value::Error(_)) => Some(Ordering::Greater),
174            (Value::Type(a), Value::Type(b)) => a.partial_cmp(b),
175            (Value::Type(_), _) => Some(Ordering::Less),
176            (_, Value::Type(_)) => Some(Ordering::Greater),
177            (Value::None, _) => Some(Ordering::Less),
178            (_, Value::None) => Some(Ordering::Greater),
179            (Value::Bool(a), Value::Bool(b)) => a.partial_cmp(b),
180            (Value::Bool(_), _) => Some(Ordering::Less),
181            (_, Value::Bool(_)) => Some(Ordering::Greater),
182            (Value::Number(a), Value::Number(b)) => a.partial_cmp(b),
183            (Value::Number(_), _) => Some(Ordering::Less),
184            (_, Value::Number(_)) => Some(Ordering::Greater),
185            (Value::Range(a), Value::Range(b)) => a.partial_cmp(b),
186            (Value::Range(_), _) => Some(Ordering::Less),
187            (_, Value::Range(_)) => Some(Ordering::Greater),
188            (Value::String(a), Value::String(b)) => a.partial_cmp(b),
189            (Value::String(_), _) => Some(Ordering::Less),
190            (_, Value::String(_)) => Some(Ordering::Greater),
191            (Value::Tuple(a), Value::Tuple(b)) => a.partial_cmp(b),
192            (Value::Tuple(_), _) => Some(Ordering::Less),
193            (_, Value::Tuple(_)) => Some(Ordering::Greater),
194            (Value::List(a), Value::List(b)) => a.partial_cmp(b),
195            (Value::List(_), _) => Some(Ordering::Less),
196            (_, Value::List(_)) => Some(Ordering::Greater),
197            (Value::Map(a), Value::Map(b)) => a.into_iter().partial_cmp(b),
198        }
199    }
200}
201
202impl Value {
203    #[inline]
204    pub fn to_number(&self) -> Result<Number, VMError> {
205        match self {
206            Value::None => Ok(Number::zero()),
207            Value::Bool(b) => {
208                let n = if *b { Number::one() } else { Number::zero() };
209                Ok(n)
210            }
211            Value::Number(n) => Ok(*n),
212            Value::String(s) => match s.parse() {
213                Ok(n) => Ok(n),
214                Err(e) => Err(VMError::ConversionError(format!(
215                    "Cannot convert {s} to Number: {e}"
216                ))),
217            },
218            v => Err(VMError::ConversionError(format!(
219                "Cannot convert {v} to Number"
220            ))),
221        }
222    }
223
224    #[inline]
225    pub fn to_float(&self) -> Result<f64, VMError> {
226        Ok(self.to_number()?.to_float())
227    }
228
229    #[inline]
230    pub fn to_int(&self) -> Result<i64, VMError> {
231        Ok(self.to_number()?.to_int())
232    }
233
234    #[inline]
235    pub fn to_usize(&self) -> Result<usize, VMError> {
236        self.to_number()?.to_usize()
237    }
238
239    pub fn as_bool(&mut self) -> &mut bool {
240        if let Value::Bool(m) = self {
241            return m;
242        }
243
244        *self = Value::Bool(self.to_bool());
245        self.as_bool()
246    }
247
248    pub fn as_float(&mut self) -> Result<&mut f64, VMError> {
249        if let Value::Number(m) = self {
250            return match m {
251                Number::Int(_) => {
252                    *m = Number::Float(m.to_float());
253                    let Number::Float(f) = m else { unreachable!() };
254                    Ok(f)
255                }
256                Number::Float(f) => Ok(f),
257            };
258        }
259
260        *self = Value::Number(Number::Float(self.to_float()?));
261        self.as_float()
262    }
263
264    pub fn as_number(&mut self) -> Result<&mut Number, VMError> {
265        if let Value::Number(m) = self {
266            return Ok(m);
267        }
268
269        *self = Value::Number(self.to_number()?);
270        self.as_number()
271    }
272
273    pub fn as_int(&mut self) -> Result<&mut i64, VMError> {
274        if let Value::Number(m) = self {
275            return match m {
276                Number::Int(i) => Ok(i),
277                Number::Float(_) => {
278                    *m = Number::Int(m.to_int());
279                    let Number::Int(i) = m else { unreachable!() };
280                    Ok(i)
281                }
282            };
283        }
284
285        *self = Value::Number(Number::Int(self.to_int()?));
286        self.as_int()
287    }
288
289    pub fn as_string(&mut self) -> &mut String {
290        if let Value::String(m) = self {
291            return m;
292        }
293
294        *self = Value::String(self.to_string());
295        self.as_string()
296    }
297
298    pub fn as_map(&mut self) -> &mut IndexMap<Value, Value> {
299        if let Value::Map(m) = self {
300            return m;
301        }
302
303        *self = Value::Map(self.to_map());
304        self.as_map()
305    }
306
307    pub fn as_list(&mut self) -> &mut Vec<Value> {
308        if let Value::List(m) = self {
309            return m;
310        }
311
312        *self = Value::List(self.to_list());
313        self.as_list()
314    }
315
316    #[inline]
317    pub fn to_bool(&self) -> bool {
318        match self {
319            Value::None => false,
320            Value::Error(_) => false,
321            Value::Type(_) => false,
322            Value::Bool(b) => *b,
323            Value::Number(n) => !n.is_zero(),
324            Value::String(s) => {
325                let empty = s.is_empty();
326                if empty {
327                    return false;
328                }
329
330                s.parse().unwrap_or(true)
331            }
332            Value::Tuple(l) => !l.is_empty(),
333            Value::List(l) => !l.is_empty(),
334            Value::Map(m) => !m.is_empty(),
335            Value::Range(r) => !r.is_empty(),
336        }
337    }
338
339    pub fn to_list(&self) -> Vec<Value> {
340        match self {
341            Value::None => vec![],
342            Value::Bool(b) => {
343                if *b {
344                    vec![Value::Bool(*b)]
345                } else {
346                    vec![]
347                }
348            }
349            Value::Number(n) => {
350                vec![(*n).into()]
351            }
352            Value::String(s) => s.chars().map(|c| Value::String(c.to_string())).collect(),
353            Value::List(l) | Value::Tuple(l) => l.clone(),
354            Value::Map(m) => {
355                let mut result = Vec::with_capacity(m.len());
356                for (k, v) in m {
357                    match k {
358                        Value::Number(i) => match i.to_usize() {
359                            Ok(index) => {
360                                result.insert(index, v.clone());
361                            }
362                            Err(_) => return vec![Value::Map(m.clone())],
363                        },
364                        _ => return vec![Value::Map(m.clone())],
365                    }
366                }
367                result
368            }
369            Value::Range(r) => r.to_list(),
370            Value::Error(e) => vec![Value::Error(e.clone())],
371            Value::Type(e) => vec![Value::Type(e.clone())],
372        }
373    }
374
375    pub fn to_map(&self) -> IndexMap<Value, Value> {
376        match self {
377            Value::None => IndexMap::new(),
378            Value::Bool(b) => {
379                if *b {
380                    IndexMap::from([(Value::Bool(*b), Value::Bool(*b))])
381                } else {
382                    IndexMap::new()
383                }
384            }
385            Value::Number(n) => IndexMap::from([((*n).into(), (*n).into())]),
386            Value::String(s) => {
387                let s = s.clone();
388                IndexMap::from([(s.clone().into(), s.into())])
389            }
390            Value::List(l) => l.iter().map(|v| (v.clone(), v.clone())).collect(),
391            Value::Tuple(l) => l
392                .chunks(2)
393                .map(|v| {
394                    let [k, v] = v else {
395                        return (v[0].clone(), Value::None);
396                    };
397                    (k.clone(), v.clone())
398                })
399                .collect(),
400            Value::Map(m) => m.clone(),
401            Value::Error(e) => {
402                let e = e.clone();
403                IndexMap::from([(e.clone().into(), e.into())])
404            }
405            Value::Type(e) => {
406                let e = e.clone();
407                IndexMap::from([(e.clone().into(), e.into())])
408            }
409            Value::Range(r) => r.to_map(),
410        }
411    }
412
413    #[inline]
414    pub fn rigz_type(&self) -> RigzType {
415        match self {
416            Value::None => RigzType::None,
417            Value::Bool(_) => RigzType::Bool,
418            Value::Number(_) => RigzType::Number,
419            Value::String(_) => RigzType::String,
420            // todo add type info to lists & maps
421            Value::List(_) => RigzType::List(Box::new(RigzType::Any)),
422            Value::Map(_) => RigzType::Map(Box::new(RigzType::Any), Box::new(RigzType::Any)),
423            Value::Range(_) => RigzType::Range,
424            Value::Error(_) => RigzType::Error,
425            Value::Tuple(v) => RigzType::Tuple(v.iter().map(|v| v.rigz_type()).collect()),
426            Value::Type(r) => r.clone(),
427        }
428    }
429
430    #[inline]
431    pub fn cast(&self, rigz_type: &RigzType) -> Value {
432        match (self, rigz_type) {
433            (s, RigzType::Error) => Value::Error(VMError::RuntimeError(s.to_string())),
434            (_, RigzType::None) => Value::None,
435            (v, RigzType::Bool) => Value::Bool(v.to_bool()),
436            (v, RigzType::String) => Value::String(v.to_string()),
437            (v, RigzType::Number) => match v.to_number() {
438                Err(e) => e.into(),
439                Ok(n) => n.into(),
440            },
441            (s, RigzType::Any) => s.clone(),
442            (v, RigzType::Int) => match v.to_int() {
443                Err(_) => {
444                    VMError::ConversionError(format!("Cannot convert {} to Int", v)).to_value()
445                }
446                Ok(n) => n.into(),
447            },
448            (v, RigzType::Float) => match v.to_float() {
449                Err(_) => {
450                    VMError::ConversionError(format!("Cannot convert {} to Float", v)).to_value()
451                }
452                Ok(n) => n.into(),
453            },
454            (v, RigzType::List(_)) => Value::List(v.to_list()),
455            (v, RigzType::Map(_, _)) => Value::Map(v.to_map()),
456            (v, RigzType::Custom(def)) => {
457                let mut res = v.to_map();
458                for (field, rigz_type) in &def.fields {
459                    match res.get_mut(&Value::String(field.clone())) {
460                        None => {
461                            return VMError::ConversionError(format!(
462                                "Cannot convert value {} to {}, missing {}",
463                                v, def.name, field
464                            ))
465                            .to_value()
466                        }
467                        Some(current) => *current = current.clone().cast(rigz_type),
468                    }
469                }
470                Value::Map(res)
471            }
472            (v, t) => VMError::ConversionError(format!("Cannot convert value {} to {:?}", v, t))
473                .to_value(),
474        }
475    }
476
477    pub fn get(&self, attr: &Value) -> Result<Option<Value>, VMError> {
478        let v = match (self, attr) {
479            // todo support ranges as attr
480            (Value::String(source), Value::Number(n)) => match n.to_usize() {
481                Ok(index) => match source.chars().nth(index) {
482                    None => return Ok(None),
483                    Some(c) => Value::String(c.to_string()),
484                },
485                Err(e) => e.into(),
486            },
487            (Value::List(source), Value::Number(n)) | (Value::Tuple(source), Value::Number(n)) => {
488                match n.to_usize() {
489                    Ok(index) => match source.get(index) {
490                        None => return Ok(None),
491                        Some(c) => c.clone(),
492                    },
493                    Err(e) => e.into(),
494                }
495            }
496            (Value::Map(source), index) => match source.get(index) {
497                None => {
498                    if let Value::Number(index) = index {
499                        if let Ok(index) = index.to_usize() {
500                            return Ok(source
501                                .get_index(index)
502                                .map(|(k, v)| Value::Tuple(vec![k.clone(), v.clone()])));
503                        }
504                    }
505                    return Ok(None);
506                }
507                Some(c) => c.clone(),
508            },
509            (Value::Number(source), Value::Number(n)) => {
510                Value::Bool(source.to_bits() & (1 << n.to_int()) != 0)
511            }
512            (source, attr) => {
513                return Err(VMError::UnsupportedOperation(format!(
514                    "Cannot read {} for {}",
515                    attr, source
516                )))
517            }
518        };
519        Ok(Some(v))
520    }
521}
522
523impl Display for Value {
524    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
525        match self {
526            Value::None => write!(f, "none"),
527            // todo dedicated to_string instead of debug
528            Value::Error(e) => write!(f, "{}", e),
529            Value::Type(e) => write!(f, "{}", e),
530            Value::Bool(v) => write!(f, "{}", v),
531            Value::Number(v) => write!(f, "{}", v),
532            Value::String(v) => write!(f, "{}", v),
533            Value::Range(v) => write!(f, "{}", v),
534            Value::List(l) => {
535                let mut values = String::new();
536                let len = l.len();
537                for (index, v) in l.iter().enumerate() {
538                    values.push_str(v.to_string().as_str());
539                    if index != len - 1 {
540                        values.push(',')
541                    }
542                }
543                write!(f, "[{}]", values)
544            }
545            Value::Tuple(l) => {
546                let mut values = String::new();
547                let len = l.len();
548                for (index, v) in l.iter().enumerate() {
549                    values.push_str(v.to_string().as_str());
550                    if index != len - 1 {
551                        values.push(',')
552                    }
553                }
554                write!(f, "({})", values)
555            }
556            Value::Map(m) => {
557                let mut values = String::new();
558                let len = m.len();
559                for (index, (k, v)) in m.iter().enumerate() {
560                    values.push_str(k.to_string().as_str());
561                    values.push_str(" = ");
562                    values.push_str(v.to_string().as_str());
563                    if index != len - 1 {
564                        values.push(',')
565                    }
566                }
567                write!(f, "{{{}}}", values)
568            }
569        }
570    }
571}
572
573impl Hash for Value {
574    fn hash<H: Hasher>(&self, state: &mut H) {
575        match self {
576            Value::None => 0.hash(state),
577            Value::Error(e) => e.hash(state),
578            Value::Type(e) => e.hash(state),
579            Value::Bool(b) => b.hash(state),
580            Value::Number(n) => n.hash(state),
581            Value::String(s) => s.hash(state),
582            Value::Range(s) => s.hash(state),
583            Value::List(l) | Value::Tuple(l) => {
584                for v in l {
585                    v.hash(state);
586                }
587            }
588            Value::Map(m) => {
589                for (k, v) in m {
590                    k.hash(state);
591                    v.hash(state);
592                }
593            }
594        }
595    }
596}
597
598impl PartialEq for Value {
599    fn eq(&self, other: &Self) -> bool {
600        match (self, other) {
601            (Value::None, Value::None) => true,
602            (Value::Error(a), Value::Error(b)) => *a == *b,
603            (Value::Type(a), Value::Type(b)) => *a == *b,
604            (Value::None, Value::Bool(false)) => true,
605            (Value::None, Value::Number(n)) => n.is_zero(),
606            (Value::Bool(false), Value::Number(n)) => n.is_zero(),
607            (Value::None, Value::String(s)) => s.is_empty() || s.eq("none"),
608            (Value::None, Value::List(v)) => v.is_empty(),
609            (Value::None, Value::Map(m)) => m.is_empty(),
610            (Value::Bool(false), Value::String(s)) => s.is_empty() || s.eq("false"),
611            (Value::Bool(false), Value::List(v)) => v.is_empty(),
612            (Value::Bool(false), Value::Map(m)) => m.is_empty(),
613            (Value::Bool(true), Value::String(s)) => s.eq("true"),
614            (Value::Bool(true), Value::Number(n)) => n.is_one(),
615            (Value::Bool(false), Value::None) => true,
616            (&Value::Bool(a), &Value::Bool(b)) => a == b,
617            (Value::Number(n), Value::None) => n.is_zero(),
618            (Value::Number(n), Value::Bool(false)) => n.is_zero(),
619            (Value::String(s), Value::None) => s.is_empty() || s.eq("none"),
620            (Value::List(v), Value::None) => v.is_empty(),
621            (Value::Map(m), Value::None) => m.is_empty(),
622            (Value::String(s), Value::Bool(false)) => s.is_empty() || s.eq("false"),
623            (Value::List(v), Value::Bool(false)) => v.is_empty(),
624            (Value::Map(m), Value::Bool(false)) => m.is_empty(),
625            (Value::String(s), Value::Bool(true)) => s.eq("true"),
626            (Value::Number(n), Value::Bool(true)) => n.is_one(),
627            (&Value::Number(a), &Value::Number(b)) => a == b,
628            (Value::Range(a), Value::Range(b)) => a == b,
629            (Value::String(a), Value::String(b)) => *a == *b,
630            (Value::Tuple(a), Value::List(b)) | (Value::List(a), Value::Tuple(b)) => *a == *b,
631            (Value::List(a), Value::List(b)) | (Value::Tuple(a), Value::Tuple(b)) => *a == *b,
632            (Value::Map(a), Value::Map(b)) => *a == *b,
633            (Value::Number(n), Value::String(s)) => {
634                (s.is_empty() && n.is_zero()) || n.to_string().eq(s)
635            }
636            (Value::String(s), Value::Number(n)) => {
637                (s.is_empty() && n.is_zero()) || n.to_string().eq(s)
638            }
639            (Value::String(s), v) => s.eq(v.to_string().as_str()),
640            (v, Value::String(s)) => s.eq(v.to_string().as_str()),
641            (Value::List(a), Value::Map(b)) => a.is_empty() && b.is_empty(),
642            (Value::Map(a), Value::List(b)) => a.is_empty() && b.is_empty(),
643            (_, _) => false,
644        }
645    }
646}
647
648#[cfg(test)]
649pub mod value_tests {
650    use crate::{Number, Value};
651    use wasm_bindgen_test::*;
652
653    #[wasm_bindgen_test(unsupported = test)]
654    fn value_eq() {
655        assert_eq!(Value::None, Value::None);
656        assert_eq!(Value::None, Value::Bool(false));
657        assert_eq!(Value::None, Value::Number(Number::Int(0)));
658        assert_eq!(Value::None, Value::Number(Number::Float(0.0)));
659        assert_eq!(Value::None, Value::String(String::new()));
660        assert_eq!(Value::Bool(false), Value::String(String::new()));
661        assert_eq!(Value::Number(Number::Int(0)), Value::String(String::new()));
662    }
663}