bridge_adapters/lisp_adapters/
primitives.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! As of now for casting slosh value types to a boolean with the sl_sh_fn macro,
//! Value::* and Value::True map to bool true rust values
//! and Value::False, Value::Nil, and Value::Undefined map to bool false.

use crate::lisp_adapters::{SlFrom, SlFromRef};
use compile_state::state::SloshVm;
use slvm::{VMResult, Value};

impl SlFromRef<'_, Value> for Value {
    fn sl_from_ref(value: Value, _vm: &SloshVm) -> VMResult<Self> {
        Ok(value)
    }
}

impl SlFromRef<'_, Value> for bool {
    fn sl_from_ref(value: Value, _vm: &SloshVm) -> VMResult<Self> {
        match value {
            Value::True => Ok(true),
            Value::False => Ok(false),
            Value::Nil => Ok(false),
            Value::Undefined => panic!("Undefined is the default initialized state of a value and its presence in actual code is a VM logical error."),
            _ => Ok(true),
        }
    }
}

impl SlFrom<bool> for Value {
    fn sl_from(value: bool, _vm: &mut SloshVm) -> VMResult<Self> {
        if value {
            Ok(Value::True)
        } else {
            Ok(Value::False)
        }
    }
}

impl<T> SlFrom<Value> for Option<T>
where
    T: SlFrom<Value>,
{
    fn sl_from(value: Value, vm: &mut SloshVm) -> VMResult<Self> {
        if value.is_nil() {
            Ok(None)
        } else {
            let t = T::sl_from(value, vm)?;
            Ok(Some(t))
        }
    }
}

impl<'a, T> SlFromRef<'a, Value> for Option<T>
where
    T: SlFromRef<'a, Value>,
{
    fn sl_from_ref(value: Value, vm: &'a SloshVm) -> VMResult<Self> {
        if value.is_nil() {
            Ok(None)
        } else {
            let t = T::sl_from_ref(value, vm)?;
            Ok(Some(t))
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::lisp_adapters::{SlInto, SlIntoRef};
    use compile_state::state::new_slosh_vm;
    use slvm::Value;

    #[test]
    fn test_bool_conversions_from_rust() {
        let mut vm = new_slosh_vm();
        let vm = &mut vm;
        let f = false;
        let val: Value = f.sl_into(vm).expect("false can be converted to Value");
        assert_eq!(val, Value::False);

        let t = true;
        let val: Value = t.sl_into(vm).expect("true can be converted to Value");
        assert_eq!(val, Value::True);
    }

    #[test]
    fn test_bool_conversions_to_rust() {
        let mut vm = new_slosh_vm();
        let vm = &mut vm;
        let n = Value::Nil;
        let n: bool = n
            .sl_into_ref(vm)
            .expect("Value::Nil can be converted to bool");
        assert_eq!(n, false);

        let f = Value::False;
        let f: bool = f
            .sl_into_ref(vm)
            .expect("Value::False can be converted to bool");
        assert_eq!(f, false);

        let t = Value::True;
        let t: bool = t
            .sl_into_ref(vm)
            .expect("Value::True can be converted to bool");
        assert_eq!(t, true);
    }
}