ucglib/build/opcode/
convert.rs

1use std::convert::{From, TryFrom};
2use std::rc::Rc;
3
4use super::{Composite, Primitive, Val, Value};
5use crate::ast::{CastType, Position};
6
7use Composite::{List, Tuple};
8use Primitive::{Bool, Empty, Float, Int, Str};
9use Value::{C, F, M, P, S, T};
10
11pub struct Error {
12    val: Primitive,
13    cast_type: CastType,
14}
15
16impl Error {
17    pub fn message(&self) -> String {
18        format!("No cast from {} to {}", self.val, self.cast_type)
19    }
20}
21
22impl From<&Primitive> for String {
23    fn from(p: &Primitive) -> Self {
24        match p {
25            Primitive::Int(i) => format!("{}", i),
26            Primitive::Float(f) => format!("{}", f),
27            Primitive::Str(s) => format!("{}", s),
28            Primitive::Bool(b) => format!("{}", b),
29            Primitive::Empty => "NULL".to_owned(),
30        }
31    }
32}
33
34impl TryFrom<&Primitive> for i64 {
35    type Error = Error;
36
37    fn try_from(p: &Primitive) -> Result<Self, Self::Error> {
38        match p {
39            Primitive::Bool(_) | Primitive::Empty => Err(Error {
40                val: p.clone(),
41                cast_type: CastType::Int,
42            }),
43            Primitive::Str(s) => match s.parse::<i64>() {
44                Ok(i) => Ok(i),
45                Err(_) => Err(Error {
46                    val: Primitive::Str(s.clone()),
47                    cast_type: CastType::Int,
48                }),
49            },
50            Primitive::Float(f) => Ok(*f as i64),
51            Primitive::Int(i) => Ok(i.clone()),
52        }
53    }
54}
55
56impl TryFrom<&Primitive> for f64 {
57    type Error = Error;
58
59    fn try_from(p: &Primitive) -> Result<Self, Self::Error> {
60        match p {
61            Primitive::Bool(_) | Primitive::Empty => Err(Error {
62                val: p.clone(),
63                cast_type: CastType::Int,
64            }),
65            Primitive::Str(s) => match s.parse::<f64>() {
66                Ok(f) => Ok(f),
67                Err(_) => Err(Error {
68                    val: Primitive::Str(s.clone()),
69                    cast_type: CastType::Int,
70                }),
71            },
72            Primitive::Int(i) => Ok(*i as f64),
73            Primitive::Float(f) => Ok(f.clone()),
74        }
75    }
76}
77
78impl TryFrom<&Primitive> for bool {
79    type Error = Error;
80
81    fn try_from(p: &Primitive) -> Result<Self, Self::Error> {
82        match p {
83            Primitive::Empty | Primitive::Int(_) | Primitive::Float(_) => Err(Error {
84                val: p.clone(),
85                cast_type: CastType::Int,
86            }),
87            Primitive::Bool(b) => Ok(*b),
88            Primitive::Str(s) => match s.as_str() {
89                "true" => Ok(true),
90                "false" => Ok(false),
91                _ => Err(Error {
92                    val: Primitive::Str(s.clone()),
93                    cast_type: CastType::Int,
94                }),
95            },
96        }
97    }
98}
99
100impl From<Rc<Value>> for Val {
101    fn from(val: Rc<Value>) -> Val {
102        val.as_ref().into()
103    }
104}
105
106impl From<Value> for Val {
107    fn from(val: Value) -> Val {
108        (&val).into()
109    }
110}
111
112impl From<&Value> for Val {
113    fn from(val: &Value) -> Val {
114        match val {
115            P(Int(i)) => Val::Int(*i),
116            P(Float(f)) => Val::Float(*f),
117            P(Str(s)) => Val::Str(s.clone()),
118            P(Bool(b)) => Val::Boolean(*b),
119            C(Tuple(fs, _)) => {
120                let mut flds = Vec::new();
121                for &(ref k, ref v) in fs.iter() {
122                    let v = v.clone();
123                    flds.push((k.clone(), Rc::new(v.into())));
124                }
125                Val::Tuple(flds)
126            }
127            C(List(elems, _)) => {
128                let mut els = Vec::new();
129                for e in elems.iter() {
130                    let e = e.clone();
131                    els.push(Rc::new(e.into()));
132                }
133                Val::List(els)
134            }
135            S(_) | F(_) | M(_) | T(_) | P(Empty) => Val::Empty,
136        }
137    }
138}
139
140impl From<Rc<Val>> for Value {
141    fn from(val: Rc<Val>) -> Self {
142        val.as_ref().into()
143    }
144}
145
146impl From<Val> for Value {
147    fn from(val: Val) -> Self {
148        (&val).into()
149    }
150}
151
152impl From<&Val> for Value {
153    fn from(val: &Val) -> Self {
154        match val {
155            Val::Int(i) => P(Int(*i)),
156            Val::Float(f) => P(Float(*f)),
157            Val::Boolean(b) => P(Bool(*b)),
158            Val::Str(s) => P(Str(s.clone())),
159            Val::Empty => P(Empty),
160            Val::List(els) => {
161                let mut lst = Vec::new();
162                let mut positions = Vec::new();
163                for e in els.iter() {
164                    let e = e.clone();
165                    lst.push(Rc::new(e.into()));
166                    positions.push(Position::new(0, 0, 0));
167                }
168                // TODO(jwall): This should have a set of
169                // Positions of the same length.
170                C(List(lst, positions))
171            }
172            Val::Tuple(flds) => {
173                let mut field_list = Vec::new();
174                let mut positions = Vec::new();
175                for &(ref key, ref val) in flds.iter() {
176                    let val = val.clone();
177                    field_list.push((key.clone(), Rc::new(val.into())));
178                    positions.push((Position::new(0, 0, 0), Position::new(0, 0, 0)));
179                }
180                C(Tuple(field_list, positions))
181            }
182            Val::Env(flds) => {
183                let mut field_list = Vec::new();
184                let mut positions = Vec::new();
185                for &(ref key, ref val) in flds.iter() {
186                    field_list.push((key.clone(), Rc::new(P(Str(val.clone())))));
187                    positions.push((Position::new(0, 0, 0), Position::new(0, 0, 0)));
188                }
189                C(Tuple(field_list, positions))
190            }
191        }
192    }
193}
194
195impl From<&Composite> for String {
196    fn from(c: &Composite) -> Self {
197        let mut buf = String::new();
198        match c {
199            &List(ref elems, _) => {
200                buf.push_str("[");
201                for e in elems.iter() {
202                    let val: String = e.as_ref().into();
203                    buf.push_str(&val);
204                    buf.push_str(",");
205                }
206                buf.push_str("]");
207            }
208            &Tuple(ref flds, _) => {
209                buf.push_str("{");
210                for &(ref k, ref v) in flds.iter() {
211                    buf.push_str(&k);
212                    buf.push_str(" = ");
213                    let val: String = v.as_ref().into();
214                    buf.push_str(&val);
215                    buf.push_str(",");
216                }
217                buf.push_str("}");
218            }
219        }
220        buf
221    }
222}
223
224impl From<&Value> for String {
225    fn from(v: &Value) -> Self {
226        match v {
227            &S(ref s) => s.clone(),
228            &P(ref p) => p.into(),
229            &C(ref c) => c.into(),
230            &T(_) => "<Thunk>".to_owned(),
231            &F(_) => "<Func>".to_owned(),
232            &M(_) => "<Module>".to_owned(),
233        }
234    }
235}