anathema_value_resolver/
value.rs

1use std::borrow::Cow;
2use std::ops::{Deref, DerefMut};
3
4use anathema_state::{Color, Hex, PendingValue, SubTo, Subscriber, Type};
5use anathema_store::smallmap::SmallMap;
6use anathema_templates::Expression;
7
8use crate::attributes::ValueKey;
9use crate::expression::{ValueExpr, ValueResolutionContext, resolve_value};
10use crate::immediate::Resolver;
11use crate::{AttributeStorage, ResolverCtx};
12
13pub type Values<'bp> = SmallMap<ValueKey<'bp>, Value<'bp>>;
14
15pub fn resolve<'bp>(expr: &'bp Expression, ctx: &ResolverCtx<'_, 'bp>, sub: impl Into<Subscriber>) -> Value<'bp> {
16    let resolver = Resolver::new(ctx);
17    let value_expr = resolver.resolve(expr);
18    Value::new(value_expr, sub.into(), ctx.attribute_storage)
19}
20
21pub fn resolve_collection<'bp>(
22    expr: &'bp Expression,
23    ctx: &ResolverCtx<'_, 'bp>,
24    sub: impl Into<Subscriber>,
25) -> Collection<'bp> {
26    let value = resolve(expr, ctx, sub);
27    Collection(value)
28}
29
30#[derive(Debug)]
31pub struct Collection<'bp>(pub(crate) Value<'bp>);
32
33impl<'bp> Collection<'bp> {
34    pub fn reload(&mut self, attributes: &AttributeStorage<'bp>) {
35        self.0.reload(attributes)
36    }
37
38    pub fn len(&self) -> usize {
39        match &self.0.kind {
40            ValueKind::List(vec) => vec.len(),
41            ValueKind::DynList(value) => {
42                let Some(state) = value.as_state() else { return 0 };
43                let Some(list) = state.as_any_list() else { return 0 };
44                list.len()
45            }
46            ValueKind::Int(_)
47            | ValueKind::Float(_)
48            | ValueKind::Bool(_)
49            | ValueKind::Char(_)
50            | ValueKind::Hex(_)
51            | ValueKind::Color(_)
52            | ValueKind::Str(_)
53            | ValueKind::DynMap(_)
54            | ValueKind::Map
55            | ValueKind::Composite(_)
56            | ValueKind::Attributes
57            | ValueKind::Null => 0,
58        }
59    }
60}
61
62/// This is the final value for a node attribute / value.
63/// This should be evaluated fully for the `ValueKind`
64#[derive(Debug)]
65pub struct Value<'bp> {
66    pub(crate) expr: ValueExpr<'bp>,
67    pub(crate) sub: Subscriber,
68    pub(crate) kind: ValueKind<'bp>,
69    pub(crate) sub_to: SubTo,
70}
71
72impl<'bp> Value<'bp> {
73    pub fn new(expr: ValueExpr<'bp>, sub: Subscriber, attribute_storage: &AttributeStorage<'bp>) -> Self {
74        let mut sub_to = SubTo::Zero;
75        let mut ctx = ValueResolutionContext::new(attribute_storage, sub, &mut sub_to);
76        let kind = resolve_value(&expr, &mut ctx);
77
78        // NOTE
79        // This is a special edge case where the map or state is used
80        // as a final value `Option<ValueKind>`.
81        //
82        // This would only hold value in an if-statement:
83        // ```
84        // if state.opt_map
85        //     text "show this if there is a map"
86        // ```
87        match kind {
88            ValueKind::DynMap(pending) | ValueKind::Composite(pending) => {
89                pending.subscribe(ctx.sub);
90                ctx.sub_to.push(pending.sub_key());
91            }
92            _ => {}
93        }
94        Self {
95            expr,
96            sub,
97            kind,
98            sub_to,
99        }
100    }
101
102    pub fn truthiness(&self) -> bool {
103        // None         = false
104        // 0            = false
105        // Some("")     = false
106        // Some(0)      = false
107        // []           = false
108        // {}           = false
109        // Some(bool)   = bool
110        // _            = true
111        self.kind.truthiness()
112    }
113
114    #[doc(hidden)]
115    pub fn kind(&self) -> &ValueKind<'_> {
116        &self.kind
117    }
118
119    pub fn reload(&mut self, attribute_storage: &AttributeStorage<'bp>) {
120        self.sub_to.unsubscribe(self.sub);
121        let mut ctx = ValueResolutionContext::new(attribute_storage, self.sub, &mut self.sub_to);
122        self.kind = resolve_value(&self.expr, &mut ctx);
123    }
124
125    pub fn try_as<T>(&self) -> Option<T>
126    where
127        T: for<'a> TryFrom<&'a ValueKind<'a>>,
128    {
129        (&self.kind).try_into().ok()
130    }
131
132    pub fn strings<F>(&self, mut f: F)
133    where
134        F: FnMut(&str) -> bool,
135    {
136        self.kind.strings(&mut f);
137    }
138}
139
140impl Drop for Value<'_> {
141    fn drop(&mut self) {
142        self.sub_to.unsubscribe(self.sub);
143    }
144}
145
146impl<'a> Deref for Value<'a> {
147    type Target = ValueKind<'a>;
148
149    fn deref(&self) -> &Self::Target {
150        &self.kind
151    }
152}
153
154impl<'a> DerefMut for Value<'a> {
155    fn deref_mut(&mut self) -> &mut Self::Target {
156        &mut self.kind
157    }
158}
159
160/// This value can never be part of an evaluation chain, only the return value.
161/// It should only ever be the final type that is held by a `Value`, at
162/// the end of an evaluation
163#[derive(Debug, PartialEq, PartialOrd, Clone)]
164pub enum ValueKind<'bp> {
165    Int(i64),
166    Float(f64),
167    Bool(bool),
168    Char(char),
169    Hex(Hex),
170    Color(Color),
171    Str(Cow<'bp, str>),
172    Null,
173
174    // NOTE
175    // The map is the final value, and is never used as part
176    // of an index, for that reason the map doesn't hold any values.
177    Map,
178    // NOTE
179    // The attributes is the final value, and is never used as part
180    // of an index, for that reason the attributes doesn't hold any values.
181    Attributes,
182    List(Box<[ValueKind<'bp>]>),
183    DynList(PendingValue),
184    DynMap(PendingValue),
185    Composite(PendingValue),
186}
187
188impl ValueKind<'_> {
189    pub fn to_int(&self) -> Option<i64> {
190        match self.as_int() {
191            Some(val) => Some(val),
192            None => Some(self.as_float()? as i64),
193        }
194    }
195
196    pub fn as_int(&self) -> Option<i64> {
197        let ValueKind::Int(i) = self else { return None };
198        Some(*i)
199    }
200
201    pub fn as_float(&self) -> Option<f64> {
202        let ValueKind::Float(i) = self else { return None };
203        Some(*i)
204    }
205
206    pub fn as_bool(&self) -> Option<bool> {
207        let ValueKind::Bool(b) = self else { return None };
208        Some(*b)
209    }
210
211    pub fn as_char(&self) -> Option<char> {
212        let ValueKind::Char(i) = self else { return None };
213        Some(*i)
214    }
215
216    pub fn as_hex(&self) -> Option<Hex> {
217        let ValueKind::Hex(i) = self else { return None };
218        Some(*i)
219    }
220
221    pub fn as_color(&self) -> Option<Color> {
222        let ValueKind::Color(i) = self else { return None };
223        Some(*i)
224    }
225
226    pub fn as_str(&self) -> Option<&str> {
227        let ValueKind::Str(i) = &self else { return None };
228        Some(i)
229    }
230
231    pub fn as_list(&self) -> Option<&[Self]> {
232        let ValueKind::List(list) = &self else { return None };
233        Some(list)
234    }
235
236    pub fn is_null(&self) -> bool {
237        matches!(self, ValueKind::Null)
238    }
239
240    pub fn strings<F>(&self, mut f: F)
241    where
242        F: FnMut(&str) -> bool,
243    {
244        self.internal_strings(&mut f);
245    }
246
247    fn internal_strings<F>(&self, f: &mut F) -> bool
248    where
249        F: FnMut(&str) -> bool,
250    {
251        match self {
252            ValueKind::Int(n) => f(&n.to_string()),
253            ValueKind::Float(n) => f(&n.to_string()),
254            ValueKind::Bool(b) => f(&b.to_string()),
255            ValueKind::Char(c) => f(&c.to_string()),
256            ValueKind::Hex(x) => f(&x.to_string()),
257            ValueKind::Color(col) => f(&col.to_string()),
258            ValueKind::Str(cow) => f(cow.as_ref()),
259            ValueKind::List(vec) => vec.iter().take_while(|val| val.internal_strings(f)).count() == vec.len(),
260            ValueKind::DynList(value) => dyn_string(*value, f),
261            ValueKind::DynMap(_) => f("<dyn map>"),
262            ValueKind::Map => f("<map>"),
263            ValueKind::Composite(_) => f("<composite>"),
264            ValueKind::Attributes => f("<attributes>"),
265            ValueKind::Null => true,
266        }
267    }
268
269    pub(crate) fn truthiness(&self) -> bool {
270        match self {
271            ValueKind::Int(0) | ValueKind::Float(0.0) | ValueKind::Bool(false) => false,
272            ValueKind::Str(cow) if cow.is_empty() => false,
273            ValueKind::Null => false,
274            ValueKind::List(list) if list.is_empty() => false,
275            ValueKind::DynList(list) => {
276                let Some(state) = list.as_state() else { return false };
277                let Some(state) = state.as_any_list() else { return false };
278                !state.is_empty()
279            }
280            ValueKind::DynMap(map) => {
281                let Some(state) = map.as_state() else { return false };
282                let Some(state) = state.as_any_map() else { return false };
283                !state.is_empty()
284            }
285            // ValueKind::Map => ??,
286            _ => true,
287        }
288    }
289
290    pub(crate) fn value_eq(&self, other: &Self) -> bool {
291        match (self, other) {
292            (ValueKind::Int(lhs), ValueKind::Int(rhs)) => lhs == rhs,
293            (ValueKind::Float(lhs), ValueKind::Float(rhs)) => lhs == rhs,
294            (ValueKind::Bool(lhs), ValueKind::Bool(rhs)) => lhs == rhs,
295            (ValueKind::Char(lhs), ValueKind::Char(rhs)) => lhs == rhs,
296            (ValueKind::Hex(lhs), ValueKind::Hex(rhs)) => lhs == rhs,
297            (ValueKind::Color(lhs), ValueKind::Color(rhs)) => lhs == rhs,
298            (ValueKind::Str(lhs), ValueKind::Str(rhs)) => lhs == rhs,
299            (ValueKind::Null, ValueKind::Null) => true,
300            (ValueKind::Attributes, ValueKind::Attributes) => true,
301            (ValueKind::List(lhs), ValueKind::List(rhs)) => lhs == rhs,
302            (ValueKind::DynList(lhs), ValueKind::DynList(rhs)) => lhs.pending_eq(*rhs),
303            (ValueKind::DynList(lhs), ValueKind::List(rhs)) => dyn_static_eq(*lhs, rhs),
304            (ValueKind::List(lhs), ValueKind::DynList(rhs)) => dyn_static_eq(*rhs, lhs),
305            (ValueKind::DynMap(lhs), ValueKind::DynMap(rhs)) => lhs.pending_eq(*rhs),
306            (ValueKind::Composite(lhs), ValueKind::Composite(rhs)) => lhs.pending_eq(*rhs),
307            _ => false,
308        }
309    }
310
311    pub(crate) fn compare_pending(&self, pending: PendingValue) -> bool {
312        let type_info = pending.type_info();
313        let Some(rhs) = pending.as_state() else { return false };
314
315        match type_info {
316            Type::Int => compare_owned(self.as_int(), rhs.as_int()),
317            Type::Float => compare_owned(self.as_float(), rhs.as_float()),
318            Type::Char => compare_owned(self.as_char(), rhs.as_char()),
319            Type::Bool => compare_owned(self.as_bool(), rhs.as_bool()),
320            Type::Hex => compare_owned(self.as_hex(), rhs.as_hex()),
321            Type::Color => compare_owned(self.as_color(), rhs.as_color()),
322            Type::String => compare_owned(self.as_str(), rhs.as_str()),
323            Type::Map => false,
324            Type::List => match self {
325                ValueKind::List(rhs) => dyn_static_eq(pending, rhs),
326                ValueKind::DynList(rhs) => rhs.pending_eq(pending),
327                _ => false,
328            },
329            Type::Composite => match self {
330                ValueKind::Composite(pending_value) => pending.pending_eq(*pending_value),
331                _ => false,
332            },
333            Type::Unit => self.is_null(),
334            Type::Maybe => unreachable!("ValueKind can never be a Maybe as it's the final value"),
335        }
336    }
337}
338
339fn compare_owned<T: PartialEq>(lhs: Option<T>, rhs: Option<T>) -> bool {
340    lhs.is_some() && lhs == rhs
341}
342
343fn dyn_static_eq(pending: PendingValue, val_kind: &[ValueKind<'_>]) -> bool {
344    let Some(state) = pending.as_state() else { return false };
345    let Some(lhs) = state.as_any_list() else { return false };
346
347    if lhs.len() != val_kind.len() {
348        return false;
349    }
350
351    for (lhs, rhs) in lhs.iter().zip(val_kind) {
352        if !rhs.compare_pending(lhs) {
353            return false;
354        }
355    }
356
357    true
358}
359
360fn dyn_string<F>(value: PendingValue, f: &mut F) -> bool
361where
362    F: FnMut(&str) -> bool,
363{
364    let Some(state) = value.as_state() else { return true };
365    let Some(list) = state.as_any_list() else { return true };
366    for i in 0..list.len() {
367        let value = list.lookup(i).expect("the value exists");
368        let Some(state) = value.as_state() else { continue };
369        let should_continue = match value.type_info() {
370            Type::Int => f(&state.as_int().expect("type info dictates this").to_string()),
371            Type::Float => f(&state.as_float().expect("type info dictates this").to_string()),
372            Type::Char => f(&state.as_char().expect("type info dictates this").to_string()),
373            Type::String => f(state.as_str().expect("type info dictates this")),
374            Type::Bool => f(&state.as_bool().expect("type info dictates this").to_string()),
375            Type::Hex => f(&state.as_hex().expect("type info dictates this").to_string()),
376            Type::Map => f("<map>"),
377            Type::List => dyn_string(value, f),
378            Type::Composite => f(&state.as_hex().expect("type info dictates this").to_string()),
379            Type::Unit => f(""),
380            Type::Color => f(&state.as_color().expect("type info dictates this").to_string()),
381            Type::Maybe => panic!(),
382        };
383
384        if !should_continue {
385            return false;
386        }
387    }
388    true
389}
390
391// -----------------------------------------------------------------------------
392//   - From impls -
393// -----------------------------------------------------------------------------
394macro_rules! from_int {
395    ($int:ty) => {
396        impl From<$int> for ValueKind<'_> {
397            fn from(value: $int) -> Self {
398                ValueKind::Int(value as i64)
399            }
400        }
401    };
402}
403
404from_int!(i64);
405from_int!(i32);
406from_int!(i16);
407from_int!(i8);
408from_int!(u64);
409from_int!(u32);
410from_int!(u16);
411from_int!(u8);
412
413impl From<f64> for ValueKind<'_> {
414    fn from(value: f64) -> Self {
415        ValueKind::Float(value)
416    }
417}
418
419impl From<f32> for ValueKind<'_> {
420    fn from(value: f32) -> Self {
421        ValueKind::Float(value as f64)
422    }
423}
424
425impl From<bool> for ValueKind<'_> {
426    fn from(value: bool) -> Self {
427        ValueKind::Bool(value)
428    }
429}
430
431impl From<char> for ValueKind<'_> {
432    fn from(value: char) -> Self {
433        ValueKind::Char(value)
434    }
435}
436
437impl From<Hex> for ValueKind<'_> {
438    fn from(value: Hex) -> Self {
439        ValueKind::Hex(value)
440    }
441}
442
443impl From<Color> for ValueKind<'_> {
444    fn from(value: Color) -> Self {
445        ValueKind::Color(value)
446    }
447}
448
449impl<'bp, T> From<Vec<T>> for ValueKind<'bp>
450where
451    T: Into<ValueKind<'bp>>,
452{
453    fn from(value: Vec<T>) -> Self {
454        let list = value.into_iter().map(T::into).collect();
455        ValueKind::List(list)
456    }
457}
458
459impl<'a> From<&'a str> for ValueKind<'a> {
460    fn from(value: &'a str) -> Self {
461        ValueKind::Str(Cow::Borrowed(value))
462    }
463}
464
465impl From<String> for ValueKind<'_> {
466    fn from(value: String) -> Self {
467        ValueKind::Str(value.into())
468    }
469}
470
471// -----------------------------------------------------------------------------
472//   - Try From -
473// -----------------------------------------------------------------------------
474macro_rules! try_from_valuekind {
475    ($t:ty, $kind:ident) => {
476        impl TryFrom<&ValueKind<'_>> for $t {
477            type Error = ();
478
479            fn try_from(value: &ValueKind<'_>) -> Result<Self, Self::Error> {
480                match value {
481                    ValueKind::$kind(val) => Ok(*val),
482                    _ => Err(()),
483                }
484            }
485        }
486    };
487}
488
489macro_rules! try_from_valuekind_int {
490    ($t:ty, $kind:ident) => {
491        impl TryFrom<&ValueKind<'_>> for $t {
492            type Error = ();
493
494            fn try_from(value: &ValueKind<'_>) -> Result<Self, Self::Error> {
495                match value {
496                    ValueKind::$kind(val) => Ok(*val as $t),
497                    _ => Err(()),
498                }
499            }
500        }
501    };
502}
503
504try_from_valuekind!(i64, Int);
505try_from_valuekind!(f64, Float);
506try_from_valuekind!(bool, Bool);
507try_from_valuekind!(Hex, Hex);
508try_from_valuekind!(Color, Color);
509
510try_from_valuekind_int!(usize, Int);
511try_from_valuekind_int!(isize, Int);
512try_from_valuekind_int!(i32, Int);
513try_from_valuekind_int!(f32, Float);
514try_from_valuekind_int!(i16, Int);
515try_from_valuekind_int!(i8, Int);
516try_from_valuekind_int!(u32, Int);
517try_from_valuekind_int!(u64, Int);
518try_from_valuekind_int!(u16, Int);
519try_from_valuekind_int!(u8, Int);
520
521impl<'bp> TryFrom<&ValueKind<'bp>> for char {
522    type Error = ();
523
524    fn try_from(value: &ValueKind<'bp>) -> Result<Self, Self::Error> {
525        match value {
526            ValueKind::Char(c) => Ok(*c),
527            ValueKind::Str(s) => s.chars().next().ok_or(()),
528            _ => Err(()),
529        }
530    }
531}
532
533impl<'a, 'bp> TryFrom<&'a ValueKind<'bp>> for &'a str {
534    type Error = ();
535
536    fn try_from(value: &'a ValueKind<'bp>) -> Result<Self, Self::Error> {
537        match value {
538            ValueKind::Str(Cow::Borrowed(val)) => Ok(val),
539            ValueKind::Str(Cow::Owned(val)) => Ok(val.as_str()),
540            _ => Err(()),
541        }
542    }
543}
544
545#[cfg(test)]
546pub(crate) mod test {
547    use anathema_state::{Hex, Map, Maybe, States};
548    use anathema_templates::Variables;
549    use anathema_templates::expressions::{
550        add, and, boolean, chr, div, either, eq, float, greater_than, greater_than_equal, hex, ident, index, less_than,
551        less_than_equal, list, map, modulo, mul, neg, not, num, or, strlit, sub, text_segments,
552    };
553
554    use crate::ValueKind;
555    use crate::testing::setup;
556
557    #[test]
558    fn attribute_lookup() {
559        let expr = index(ident("attributes"), strlit("a"));
560        let int = num(123);
561
562        let mut states = States::new();
563        setup(&mut states, Default::default(), |test| {
564            test.set_attribute("a", &int);
565            let value = test.eval(&expr);
566            assert_eq!(123, value.as_int().unwrap());
567        });
568    }
569
570    #[test]
571    fn expr_list_dyn_index() {
572        let expr = index(list([1, 2, 3]), add(ident("index"), num(1)));
573
574        let mut states = States::new();
575        let mut globals = Variables::new();
576        globals.declare("index", 0);
577
578        setup(&mut states, globals, |test| {
579            let value = test.eval(&expr);
580            assert_eq!(2, value.as_int().unwrap());
581        });
582    }
583
584    #[test]
585    fn expr_list() {
586        let expr = index(list([1, 2, 3]), num(0));
587
588        let mut states = States::new();
589        setup(&mut states, Default::default(), |test| {
590            let value = test.eval(&expr);
591            assert_eq!(1, value.as_int().unwrap());
592        });
593    }
594
595    #[test]
596    fn either_index() {
597        // state[0] ? attributes[0]
598        let expr = either(
599            index(index(ident("state"), strlit("list")), num(0)),
600            index(index(ident("attributes"), strlit("list")), num(0)),
601        );
602
603        let list = list([strlit("from attribute")]);
604
605        let mut states = States::new();
606        setup(&mut states, Default::default(), |test| {
607            // Set list for attributes
608            test.set_attribute("list", &list);
609
610            // Evaluate the value.
611            // The state is not yet set so it will fall back to attributes
612            let mut value = test.eval(&expr);
613            assert_eq!("from attribute", value.as_str().unwrap());
614
615            // Set the state value
616            test.with_state(|state| state.list.push("from state"));
617
618            // The value now comes from the state
619            value.reload(&test.attributes);
620            assert_eq!("from state", value.as_str().unwrap());
621        });
622    }
623
624    #[test]
625    fn either_then_index() {
626        // (state ? attributes)[0]
627
628        let list = list([num(123)]);
629        let mut states = States::new();
630        setup(&mut states, Default::default(), |test| {
631            let expr = index(
632                either(
633                    index(ident("attributes"), strlit("list")),
634                    index(ident("state"), strlit("list")),
635                ),
636                num(0),
637            );
638
639            test.with_state(|state| state.list.push("a string"));
640            let value = test.eval(&expr);
641            assert_eq!("a string", value.as_str().unwrap());
642
643            test.set_attribute("list", &list);
644            let value = test.eval(&expr);
645            assert_eq!(123, value.as_int().unwrap());
646        });
647    }
648
649    #[test]
650    fn either_or() {
651        let mut states = States::new();
652        setup(&mut states, Default::default(), |test| {
653            test.with_state(|state| state.num.set(1));
654            test.with_state(|state| state.num_2.set(2));
655
656            // There is no c, so use b
657            let expr = either(
658                index(ident("state"), strlit("num_3")),
659                index(ident("state"), strlit("num_2")),
660            );
661            let value = test.eval(&expr);
662            assert_eq!(2, value.as_int().unwrap());
663
664            // There is a, so don't use b
665            let expr = either(
666                index(ident("state"), strlit("num")),
667                index(ident("state"), strlit("num_2")),
668            );
669            let value = test.eval(&expr);
670            assert_eq!(1, value.as_int().unwrap());
671        });
672    }
673
674    #[test]
675    fn mods() {
676        let mut states = States::new();
677        setup(&mut states, Default::default(), |test| {
678            test.with_state(|state| state.num.set(5));
679            let lookup = index(ident("state"), strlit("num"));
680            let expr = modulo(lookup, num(3));
681            let value = test.eval(&expr);
682            assert_eq!(2, value.as_int().unwrap());
683        });
684    }
685
686    #[test]
687    fn division() {
688        let mut states = States::new();
689        setup(&mut states, Default::default(), |test| {
690            test.with_state(|state| state.num.set(6));
691            let lookup = index(ident("state"), strlit("num"));
692            let expr = div(lookup, num(2));
693            let value = test.eval(&expr);
694            assert_eq!(3, value.as_int().unwrap());
695        });
696    }
697
698    #[test]
699    fn multiplication() {
700        let mut states = States::new();
701        setup(&mut states, Default::default(), |test| {
702            test.with_state(|state| state.num.set(2));
703            let lookup = index(ident("state"), strlit("num"));
704            let expr = mul(lookup, num(2));
705            let value = test.eval(&expr);
706            assert_eq!(4, value.as_int().unwrap());
707        });
708    }
709
710    #[test]
711    fn subtraction() {
712        let mut states = States::new();
713        setup(&mut states, Default::default(), |test| {
714            test.with_state(|state| state.num.set(1));
715            let lookup = index(ident("state"), strlit("num"));
716            let expr = sub(lookup, num(2));
717            let value = test.eval(&expr);
718            assert_eq!(-1, value.as_int().unwrap());
719        });
720    }
721
722    #[test]
723    fn addition() {
724        let mut states = States::new();
725        setup(&mut states, Default::default(), |test| {
726            test.with_state(|state| state.num.set(1));
727            let lookup = index(ident("state"), strlit("num"));
728            let expr = add(lookup, num(2));
729            let value = test.eval(&expr);
730            assert_eq!(3, value.as_int().unwrap());
731        });
732    }
733
734    #[test]
735    fn test_or() {
736        let mut states = States::new();
737        setup(&mut states, Default::default(), |test| {
738            let is_true = or(boolean(false), boolean(true));
739            let is_true = test.eval(&is_true);
740            assert!(is_true.as_bool().unwrap());
741        });
742    }
743
744    #[test]
745    fn test_and() {
746        let mut states = States::new();
747        setup(&mut states, Default::default(), |test| {
748            let is_true = and(boolean(true), boolean(true));
749            let is_true = test.eval(&is_true);
750            assert!(is_true.as_bool().unwrap());
751        });
752    }
753
754    #[test]
755    fn lte() {
756        let mut states = States::new();
757        setup(&mut states, Default::default(), |test| {
758            let is_true = less_than_equal(num(1), num(2));
759            let is_also_true = less_than_equal(num(1), num(1));
760            let is_true = test.eval(&is_true);
761            let is_also_true = test.eval(&is_also_true);
762            assert!(is_true.as_bool().unwrap());
763            assert!(is_also_true.as_bool().unwrap());
764        });
765    }
766
767    #[test]
768    fn lt() {
769        let mut states = States::new();
770        setup(&mut states, Default::default(), |test| {
771            let is_true = less_than(num(1), num(2));
772            let is_false = less_than(num(1), num(1));
773            let is_true = test.eval(&is_true);
774            let is_false = test.eval(&is_false);
775            assert!(is_true.as_bool().unwrap());
776            assert!(!is_false.as_bool().unwrap());
777        });
778    }
779
780    #[test]
781    fn gte() {
782        let mut states = States::new();
783        setup(&mut states, Default::default(), |test| {
784            let is_true = greater_than_equal(num(2), num(1));
785            let is_also_true = greater_than_equal(num(2), num(2));
786            let is_true = test.eval(&is_true);
787            let is_also_true = test.eval(&is_also_true);
788            assert!(is_true.as_bool().unwrap());
789            assert!(is_also_true.as_bool().unwrap());
790        });
791    }
792
793    #[test]
794    fn gt() {
795        let mut states = States::new();
796        setup(&mut states, Default::default(), |test| {
797            let is_true = greater_than(num(2), num(1));
798            let is_false = greater_than(num(2), num(2));
799            let is_true = test.eval(&is_true);
800            let is_false = test.eval(&is_false);
801            assert!(is_true.as_bool().unwrap());
802            assert!(!is_false.as_bool().unwrap());
803        });
804    }
805
806    #[test]
807    fn equality() {
808        let mut states = States::new();
809        setup(&mut states, Default::default(), |test| {
810            let is_true = eq(num(1), num(1));
811            let is_true = test.eval(&is_true);
812            let is_false = &not(eq(num(1), num(1)));
813            let is_false = test.eval(is_false);
814            assert!(is_true.as_bool().unwrap());
815            assert!(!is_false.as_bool().unwrap());
816        });
817    }
818
819    #[test]
820    fn neg_float() {
821        let mut states = States::new();
822        setup(&mut states, Default::default(), |test| {
823            let expr = neg(float(123.1));
824            let value = test.eval(&expr);
825            assert_eq!(-123.1, value.as_float().unwrap());
826        });
827    }
828
829    #[test]
830    fn neg_num() {
831        let mut states = States::new();
832        setup(&mut states, Default::default(), |test| {
833            let expr = neg(num(123));
834            let value = test.eval(&expr);
835            assert_eq!(-123, value.as_int().unwrap());
836        });
837    }
838
839    #[test]
840    fn not_true() {
841        let mut states = States::new();
842        setup(&mut states, Default::default(), |test| {
843            let expr = not(boolean(false));
844            let value = test.eval(&expr);
845            assert!(value.as_bool().unwrap());
846        });
847    }
848
849    #[test]
850    fn map_resolve() {
851        let mut states = States::new();
852        setup(&mut states, Default::default(), |test| {
853            let expr = map([("a", 123), ("b", 456)]);
854            let value = test.eval(&expr);
855            assert_eq!(ValueKind::Map, value.kind);
856        });
857    }
858
859    #[test]
860    fn optional_map_resolve() {
861        let mut states = States::new();
862        setup(&mut states, Default::default(), |test| {
863            // At first there is no map...
864            let expr = index(ident("state"), strlit("opt_map"));
865            let mut value = test.eval(&expr);
866            assert!(matches!(value.kind, ValueKind::Null));
867
868            // ... then we insert a map
869            test.with_state(|state| {
870                let map = Map::empty();
871                state.opt_map.set(Maybe::some(map));
872            });
873
874            value.reload(&test.attributes);
875            assert!(matches!(value.kind, ValueKind::DynMap(_)));
876        });
877    }
878
879    #[test]
880    fn str_resolve() {
881        // state[empty|full]
882        let mut states = States::new();
883        let mut globals = Variables::new();
884        globals.declare("full", "string");
885        setup(&mut states, globals, |test| {
886            let expr = index(ident("state"), either(ident("empty"), ident("full")));
887            test.with_state(|state| state.string.set("a string"));
888            let value = test.eval(&expr);
889            assert_eq!("a string", value.as_str().unwrap());
890        });
891    }
892
893    #[test]
894    fn state_string() {
895        let mut states = States::new();
896        setup(&mut states, Default::default(), |test| {
897            test.with_state(|state| state.string.set("a string"));
898            let expr = index(ident("state"), strlit("string"));
899            let value = test.eval(&expr);
900            assert_eq!("a string", value.as_str().unwrap());
901        });
902    }
903
904    #[test]
905    fn state_float() {
906        let mut states = States::new();
907        setup(&mut states, Default::default(), |test| {
908            let expr = index(ident("state"), strlit("float"));
909            test.with_state(|state| state.float.set(1.2));
910            let value = test.eval(&expr);
911            assert_eq!(1.2, value.as_float().unwrap());
912        });
913    }
914
915    #[test]
916    fn test_either() {
917        let mut states = States::new();
918        let mut globals = Variables::new();
919        globals.declare("missing", 111);
920        setup(&mut states, globals, |test| {
921            let expr = either(ident("missings"), num(2));
922            let value = test.eval(&expr);
923            assert_eq!(2, value.as_int().unwrap());
924        });
925    }
926
927    #[test]
928    fn test_hex() {
929        let mut states = States::new();
930        setup(&mut states, Default::default(), |test| {
931            let expr = hex((1, 2, 3));
932            let value = test.eval(&expr);
933            assert_eq!(Hex::from((1, 2, 3)), value.as_hex().unwrap());
934        });
935    }
936
937    #[test]
938    fn test_char() {
939        let mut states = States::new();
940        setup(&mut states, Default::default(), |test| {
941            let expr = chr('x');
942            let value = test.eval(&expr);
943            assert_eq!('x', value.as_char().unwrap());
944        });
945    }
946
947    #[test]
948    fn test_float() {
949        let mut states = States::new();
950        setup(&mut states, Default::default(), |test| {
951            let expr = float(123.123);
952            let value = test.eval(&expr);
953            assert_eq!(123.123, value.as_float().unwrap());
954        });
955    }
956
957    #[test]
958    fn test_int() {
959        let mut states = States::new();
960        setup(&mut states, Default::default(), |test| {
961            let expr = num(123);
962            let value = test.eval(&expr);
963            assert_eq!(123, value.as_int().unwrap());
964        });
965    }
966
967    #[test]
968    fn test_bool() {
969        let mut states = States::new();
970        setup(&mut states, Default::default(), |test| {
971            let expr = boolean(true);
972            let value = test.eval(&expr);
973            assert!(value.as_bool().unwrap());
974        });
975    }
976
977    #[test]
978    fn test_dyn_list() {
979        let mut states = States::new();
980        setup(&mut states, Default::default(), |test| {
981            test.with_state(|state| {
982                state.list.push("abc");
983                state.list.push("def");
984            });
985            let expr = index(index(ident("state"), strlit("list")), num(1));
986            let value = test.eval(&expr);
987            assert_eq!("def", value.as_str().unwrap());
988        });
989    }
990
991    #[test]
992    fn test_expression_map_state_key() {
993        let mut states = States::new();
994        setup(&mut states, Default::default(), |test| {
995            let expr = index(map([("value", 123)]), index(ident("state"), strlit("string")));
996            test.with_state(|state| state.string.set("value"));
997            let value = test.eval(&expr);
998            assert_eq!(123, value.as_int().unwrap());
999        });
1000    }
1001
1002    #[test]
1003    fn test_expression_map() {
1004        let mut states = States::new();
1005        setup(&mut states, Default::default(), |test| {
1006            let expr = index(map([("value", 123)]), strlit("value"));
1007            let value = test.eval(&expr);
1008            assert_eq!(123, value.as_int().unwrap());
1009        });
1010    }
1011
1012    #[test]
1013    fn test_state_lookup() {
1014        let mut states = States::new();
1015        setup(&mut states, Default::default(), |test| {
1016            let expr = index(ident("state"), strlit("num"));
1017            let value = test.eval(&expr);
1018            assert_eq!(0, value.as_int().unwrap());
1019        });
1020    }
1021
1022    #[test]
1023    fn test_nested_map() {
1024        let mut states = States::new();
1025        setup(&mut states, Default::default(), |test| {
1026            let expr = index(index(ident("state"), strlit("map")), strlit("value"));
1027            test.with_state(|state| state.map.to_mut().insert("value", 123));
1028            let value = test.eval(&expr);
1029            assert_eq!(123, value.as_int().unwrap());
1030        });
1031    }
1032
1033    // #[test]
1034    // fn test_nested_maps() {
1035    //     let mut states = States::new();
1036    //     setup(&mut states, Default::default(), |test| {
1037    //         let expr = index(
1038    //             index(index(ident("state"), strlit("value")), strlit("value")),
1039    //             strlit("value"),
1040    //         );
1041    //         let mut inner_map = Value::new(Map::empty());
1042    //         let mut inner_inner_map = Value::new(Map::empty());
1043    //         inner_inner_map.insert("value", 123);
1044    //         inner_map.insert("value", inner_inner_map);
1045
1046    //         test.set_state("value", inner_map);
1047    //         let value = test.eval(&*expr);
1048    //         assert_eq!(123, value.as_int().unwrap());
1049    //     });
1050    // }
1051
1052    #[test]
1053    fn stringify() {
1054        let mut states = States::new();
1055        setup(&mut states, Default::default(), |test| {
1056            let expr = text_segments([strlit("hello"), strlit(" "), strlit("world")]);
1057            let value = test.eval(&expr);
1058            let mut actual = String::new();
1059            value.strings(|st| {
1060                actual.push_str(st);
1061                true
1062            });
1063            assert_eq!("hello world", &actual);
1064        });
1065    }
1066}