expr/
value.rs

1use crate::Rule;
2use indexmap::IndexMap;
3use log::trace;
4use pest::iterators::{Pair, Pairs};
5use std::fmt;
6use std::fmt::{Display, Formatter};
7
8/// Represents a data value as input or output to an expr program
9#[derive(Debug, Default, Clone, PartialEq)]
10pub enum Value {
11    Number(i64),
12    Bool(bool),
13    Float(f64),
14    #[default]
15    Nil,
16    String(String),
17    Array(Vec<Value>),
18    Map(IndexMap<String, Value>),
19}
20
21impl Value {
22    pub fn as_bool(&self) -> Option<bool> {
23        match self {
24            Value::Bool(b) => Some(*b),
25            _ => None,
26        }
27    }
28
29    pub fn as_number(&self) -> Option<i64> {
30        match self {
31            Value::Number(n) => Some(*n),
32            _ => None,
33        }
34    }
35
36    pub fn as_float(&self) -> Option<f64> {
37        match self {
38            Value::Float(f) => Some(*f),
39            _ => None,
40        }
41    }
42
43    pub fn as_string(&self) -> Option<&str> {
44        match self {
45            Value::String(s) => Some(s),
46            _ => None,
47        }
48    }
49
50    pub fn as_array(&self) -> Option<&[Value]> {
51        match self {
52            Value::Array(a) => Some(a),
53            _ => None,
54        }
55    }
56
57    pub fn as_map(&self) -> Option<&IndexMap<String, Value>> {
58        match self {
59            Value::Map(m) => Some(m),
60            _ => None,
61        }
62    }
63
64    pub fn is_nil(&self) -> bool {
65        matches!(self, Value::Nil)
66    }
67}
68
69impl AsRef<Value> for Value {
70    fn as_ref(&self) -> &Value {
71        self
72    }
73}
74
75impl From<i64> for Value {
76    fn from(n: i64) -> Self {
77        Value::Number(n)
78    }
79}
80
81impl From<i32> for Value {
82    fn from(n: i32) -> Self {
83        Value::Number(n as i64)
84    }
85}
86
87impl From<usize> for Value {
88    fn from(n: usize) -> Self {
89        Value::Number(n as i64)
90    }
91}
92
93impl From<f64> for Value {
94    fn from(f: f64) -> Self {
95        Value::Float(f)
96    }
97}
98
99impl From<bool> for Value {
100    fn from(b: bool) -> Self {
101        Value::Bool(b)
102    }
103}
104
105impl From<String> for Value {
106    fn from(s: String) -> Self {
107        Value::String(s)
108    }
109}
110
111impl From<&String> for Value {
112    fn from(s: &String) -> Self {
113        s.to_string().into()
114    }
115}
116
117impl From<&str> for Value {
118    fn from(s: &str) -> Self {
119        s.to_string().into()
120    }
121}
122
123impl<V: Into<Value>> From<Vec<V>> for Value {
124    fn from(a: Vec<V>) -> Self {
125        Value::Array(a.into_iter().map(|v| v.into()).collect())
126    }
127}
128
129impl From<IndexMap<String, Value>> for Value {
130    fn from(m: IndexMap<String, Value>) -> Self {
131        Value::Map(m)
132    }
133}
134
135impl Display for Value {
136    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
137        match self {
138            Value::Number(n) => write!(f, "{n}"),
139            Value::Float(n) => write!(f, "{n}"),
140            Value::Bool(b) => write!(f, "{b}"),
141            Value::Nil => write!(f, "nil"),
142            Value::String(s) => write!(
143                f,
144                r#""{}""#,
145                s.replace("\\", "\\\\")
146                    .replace("\n", "\\n")
147                    .replace("\r", "\\r")
148                    .replace("\t", "\\t")
149                    .replace("\"", "\\\"")
150            ),
151            Value::Array(a) => write!(
152                f,
153                "[{}]",
154                a.iter()
155                    .map(|v| v.to_string())
156                    .collect::<Vec<String>>()
157                    .join(", ")
158            ),
159            Value::Map(m) => write!(
160                f,
161                "{{{}}}",
162                m.iter()
163                    .map(|(k, v)| format!("{}: {}", k, v))
164                    .collect::<Vec<String>>()
165                    .join(", ")
166            ),
167        }
168    }
169}
170
171impl From<Pairs<'_, Rule>> for Value {
172    fn from(mut pairs: Pairs<Rule>) -> Self {
173        pairs.next().unwrap().into()
174    }
175}
176
177impl From<Pair<'_, Rule>> for Value {
178    fn from(pair: Pair<Rule>) -> Self {
179        trace!("{:?} = {}", &pair.as_rule(), pair.as_str());
180        match pair.as_rule() {
181            Rule::value => pair.into_inner().into(),
182            Rule::nil => Value::Nil,
183            Rule::bool => Value::Bool(pair.as_str().parse().unwrap()),
184            Rule::int => Value::Number(pair.as_str().parse().unwrap()),
185            Rule::decimal => Value::Float(pair.as_str().parse().unwrap()),
186            Rule::string_multiline => pair.into_inner().as_str().into(),
187            Rule::string => pair
188                .into_inner()
189                .as_str()
190                .replace("\\\\", "\\")
191                .replace("\\n", "\n")
192                .replace("\\r", "\r")
193                .replace("\\t", "\t")
194                .replace("\\\"", "\"")
195                .into(),
196            // Rule::operation => {
197            //     let mut pairs = pair.into_inner();
198            //     let operator = pairs.next().unwrap().into();
199            //     let left = Box::new(pairs.next().unwrap().into());
200            //     let right = Box::new(pairs.next().unwrap().into());
201            //     Node::Operation {
202            //         operator,
203            //         left,
204            //         right,
205            //     }
206            // }
207            rule => unreachable!("Unexpected rule: {rule:?} {}", pair.as_str()),
208        }
209    }
210}