rain_lang/value/
expr.rs

1/*!
2Expression nodes
3*/
4use std::convert::{TryInto, TryFrom};
5use smallvec::{smallvec, SmallVec};
6use std::fmt::{self, Display, Debug, Formatter};
7use std::slice::Iter;
8use std::ops::{Deref, DerefMut};
9
10use super::{
11    Value, ValueDesc, ValueEnum, ValId, ValueData,
12    error::ValueError
13};
14//use crate::util::AlwaysOk;
15
16/// The size of a small S-expression
17pub const SMALL_SEXPR_SIZE: usize = 3;
18
19/// Potentially un-normalized S-expression arguments
20#[derive(Clone, PartialEq, Eq, Hash)]
21pub struct SexprArgs(pub SmallVec<[ValId; SMALL_SEXPR_SIZE]>);
22
23impl Deref for SexprArgs {
24    type Target = SmallVec<[ValId; SMALL_SEXPR_SIZE]>;
25    #[inline(always)] fn deref(&self) -> &Self::Target { &self.0 }
26}
27
28impl DerefMut for SexprArgs {
29    #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
30}
31
32impl From<SmallVec<[ValId; SMALL_SEXPR_SIZE]>> for SexprArgs {
33    #[inline] fn from(v: SmallVec<[ValId; SMALL_SEXPR_SIZE]>) -> SexprArgs { SexprArgs(v) }
34}
35
36impl SexprArgs {
37    /// Normalize this S-expression
38    #[inline(always)] pub fn normalize(self) -> Result<Sexpr, ValueError> { Sexpr::build(self) }
39    /// Get the dependencies of this argument set
40    #[inline] pub fn dependencies(&self) -> Iter<ValId> { self.iter() }
41}
42
43impl Debug for SexprArgs {
44    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
45        <Self as Display>::fmt(self, fmt)
46    }
47}
48
49impl Display for SexprArgs {
50    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
51        write!(fmt, "(")?;
52        let mut first = true;
53        for arg in self.iter().rev() {
54            write!(fmt, "{}{}", if first {""} else {" "}, arg)?;
55            first = false;
56        }
57        write!(fmt, ")")
58    }
59}
60
61impl TryFrom<SexprArgs> for Sexpr {
62    type Error = ValueError;
63    fn try_from(args: SexprArgs) -> Result<Sexpr, ValueError> {
64        args.normalize()
65    }
66}
67impl TryFrom<SexprArgs> for ValueEnum {
68    type Error = ValueError;
69    fn try_from(args: SexprArgs) -> Result<ValueEnum, ValueError> {
70        Ok(ValueEnum::from(args.normalize()?))
71    }
72}
73impl TryFrom<SexprArgs> for ValueData {
74    type Error = ValueError;
75    fn try_from(args: SexprArgs) -> Result<ValueData, ValueError> {
76        Ok(ValueData::new(ValueEnum::try_from(args)?))
77    }
78}
79impl TryFrom<SexprArgs> for ValId {
80    type Error = ValueError;
81    fn try_from(args: SexprArgs) -> Result<ValId, ValueError> {
82        let sexpr: Sexpr = args.try_into()?;
83        sexpr.try_into()
84    }
85}
86
87impl From<Sexpr> for ValueEnum { fn from(sexpr: Sexpr) -> ValueEnum { ValueEnum::Sexpr(sexpr) } }
88impl From<Sexpr> for ValueData {
89    fn from(sexpr: Sexpr) -> ValueData { ValueData::new(ValueEnum::from(sexpr)) }
90}
91impl TryFrom<Sexpr> for ValId {
92    type Error = ValueError;
93    fn try_from(sexpr: Sexpr) -> Result<ValId, ValueError> { sexpr.to_node() }
94}
95
96impl ValueDesc for Sexpr {
97    type Err = ValueError;
98    fn to_node<E>(mut self) -> Result<ValId, E> where ValueError: Into<E> {
99        if self.args.len() == 1 {
100            Ok(self.args.swap_remove(0))
101        } else {
102            ValId::try_new(ValueEnum::Sexpr(self).into()).map_err(|err| err.into())
103        }
104    }
105}
106
107impl Value for Sexpr {}
108
109/// An S-expression node
110#[derive(Debug, Clone, PartialEq, Eq, Hash)]
111pub struct Sexpr {
112    args: SexprArgs
113}
114
115impl Sexpr {
116    /// Build a sexpr contaning a single node
117    pub fn node<N: Into<ValId>>(node: N) -> Sexpr {
118        Self::build_normalized(SexprArgs(smallvec![node.into()]))
119    }
120    /// Build an S-expression from a vector of arguments, asserting they are normalized.
121    /// It is a logic error if they are not.
122    pub fn build_normalized<V>(args: V) -> Sexpr
123    where V: Into<SexprArgs> { Sexpr { args: args.into() } }
124    /// Build an S-expression from a vector of arguments
125    pub fn build<V>(args: V) -> Result<Sexpr, ValueError>
126    where V: Into<SexprArgs> {
127        let mut args: SexprArgs = args.into();
128        args.try_normalize()?;
129        Ok(Self::build_normalized(args))
130    }
131    /// Get the dependencies of this argument set
132    #[inline] pub fn dependencies(&self) -> Iter<ValId> { self.args.dependencies() }
133}
134
135impl Display for Sexpr {
136    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { write!(fmt, "{}", self.args) }
137}
138
139impl Deref for Sexpr {
140    type Target = SexprArgs;
141    #[inline(always)] fn deref(&self) -> &Self::Target { &self.args }
142}
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147    use smallvec::smallvec;
148    use crate::value::primitive::logical::{BINARY_OPS, UNARY_OPS};
149    #[test]
150    fn fully_evaluated_binary_logical_operations_normalize() {
151        for op in BINARY_OPS {
152            for i in 0b00..=0b11 {
153                let l = i & 0b01 != 0;
154                let r = i & 0b11 != 0;
155                let unnormalized = SexprArgs(smallvec![
156                    ValId::from(r),
157                    ValId::from(l),
158                    ValId::from(*op)
159                    ]);
160                let mut sexpr = unnormalized.clone();
161                match sexpr.try_normalize() {
162                    Ok(_) => {},
163                    Err(err) => {
164                        panic!(
165                            "Normalization error for {} [current state = {}]: {:#?}",
166                            unnormalized, sexpr, err
167                        )
168                    }
169                }
170                let sexpr = Sexpr::build_normalized(sexpr);
171                let res = SexprArgs(smallvec![ValId::from(op.apply(l, r))]);
172                assert!(sexpr.args_jeq(&res), "Invalid result for {}", unnormalized)
173            }
174        }
175    }
176    #[test]
177    fn partially_evaluated_binary_logical_operations_normalize() {
178        for op in BINARY_OPS {
179            for arg in &[true, false] {
180                let unnormalized = SexprArgs(smallvec![
181                    ValId::from(*arg),
182                    ValId::from(*op)
183                    ]);
184                let mut sexpr = unnormalized.clone();
185                match sexpr.try_normalize() {
186                    Ok(_) => {},
187                    Err(err) => {
188                        panic!(
189                            "Normalization error for {} [current state = {}]: {:#?}",
190                            unnormalized, sexpr, err
191                        )
192                    }
193                }
194                let sexpr = Sexpr::build_normalized(sexpr);
195                let res = SexprArgs(smallvec![ValId::from(op.partial_apply(*arg))]);
196                assert!(sexpr.args_jeq(&res), "Invalid result for {}", unnormalized);
197            }
198        }
199    }
200    #[test]
201    fn unary_logical_operations_normalize() {
202        for op in UNARY_OPS {
203            for arg in &[true, false] {
204                let unnormalized = SexprArgs(smallvec![
205                    ValId::from(*arg),
206                    ValId::from(*op)
207                    ]);
208                let mut sexpr = unnormalized.clone();
209                match sexpr.try_normalize() {
210                    Ok(_) => {},
211                    Err(err) => {
212                        panic!(
213                            "Normalization error for {} [current state = {}]: {:#?}",
214                            unnormalized, sexpr, err
215                        );
216                    }
217                }
218                let sexpr = Sexpr::build_normalized(sexpr);
219                let res = SexprArgs(smallvec![ValId::from(op.apply(*arg))]);
220                assert!(sexpr.args_jeq(&res), "Invalid result for {}", unnormalized);
221            }
222        }
223    }
224}