/rust/registry/src/index.crates.io-1949cf8c6b5b557f/serde_dhall-0.13.0/src/value.rs
Line | Count | Source |
1 | | use std::collections::{BTreeMap, HashMap}; |
2 | | use std::result::Result as StdResult; |
3 | | |
4 | | use dhall::builtins::Builtin; |
5 | | use dhall::operations::OpKind; |
6 | | use dhall::semantics::{Hir, HirKind, Nir, NirKind}; |
7 | | pub use dhall::syntax::NumKind; |
8 | | use dhall::syntax::{Expr, ExprKind, Span}; |
9 | | use dhall::Ctxt; |
10 | | |
11 | | use crate::{Error, ErrorKind, FromDhall, Result, ToDhall}; |
12 | | |
13 | | #[derive(Debug, Clone)] |
14 | | enum ValueKind { |
15 | | /// Invariant: the value must be printable with the given type. |
16 | | Val(SimpleValue, Option<SimpleType>), |
17 | | Ty(SimpleType), |
18 | | } |
19 | | |
20 | | #[doc(hidden)] |
21 | | /// An arbitrary Dhall value. |
22 | | #[derive(Debug, Clone, PartialEq, Eq)] |
23 | | pub struct Value { |
24 | | kind: ValueKind, |
25 | | } |
26 | | |
27 | | /// A value of the kind that can be decoded by `serde_dhall`, e.g. `{ x = True, y = [1, 2, 3] }`. |
28 | | /// This can be obtained with [`from_str()`] or [`from_file()`]. |
29 | | /// It can also be deserialized into Rust types with [`from_simple_value()`]. |
30 | | /// |
31 | | /// # Examples |
32 | | /// |
33 | | /// ```rust |
34 | | /// # fn main() -> serde_dhall::Result<()> { |
35 | | /// use std::collections::BTreeMap; |
36 | | /// use serde::Deserialize; |
37 | | /// use serde_dhall::{from_simple_value, NumKind, SimpleValue}; |
38 | | /// |
39 | | /// #[derive(Debug, PartialEq, Eq, Deserialize)] |
40 | | /// struct Foo { |
41 | | /// x: bool, |
42 | | /// y: Vec<u64>, |
43 | | /// } |
44 | | /// |
45 | | /// let value: SimpleValue = |
46 | | /// serde_dhall::from_str("{ x = True, y = [1, 2, 3] }").parse()?; |
47 | | /// |
48 | | /// assert_eq!( |
49 | | /// value, |
50 | | /// SimpleValue::Record({ |
51 | | /// let mut r = BTreeMap::new(); |
52 | | /// r.insert( |
53 | | /// "x".to_string(), |
54 | | /// SimpleValue::Num(NumKind::Bool(true)) |
55 | | /// ); |
56 | | /// r.insert( |
57 | | /// "y".to_string(), |
58 | | /// SimpleValue::List(vec![ |
59 | | /// SimpleValue::Num(NumKind::Natural(1)), |
60 | | /// SimpleValue::Num(NumKind::Natural(2)), |
61 | | /// SimpleValue::Num(NumKind::Natural(3)), |
62 | | /// ]) |
63 | | /// ); |
64 | | /// r |
65 | | /// }) |
66 | | /// ); |
67 | | /// |
68 | | /// let foo: Foo = from_simple_value(value)?; |
69 | | /// |
70 | | /// assert_eq!( |
71 | | /// foo, |
72 | | /// Foo { |
73 | | /// x: true, |
74 | | /// y: vec![1, 2, 3] |
75 | | /// } |
76 | | /// ); |
77 | | /// # Ok(()) |
78 | | /// # } |
79 | | /// ``` |
80 | | /// |
81 | | /// ```rust |
82 | | /// # fn main() -> serde_dhall::Result<()> { |
83 | | /// use std::collections::BTreeMap; |
84 | | /// use serde_dhall::{NumKind, SimpleValue}; |
85 | | /// |
86 | | /// let value: SimpleValue = |
87 | | /// serde_dhall::from_str("{ x = 1, y = 2 }").parse()?; |
88 | | /// |
89 | | /// let mut map = BTreeMap::new(); |
90 | | /// map.insert("x".to_string(), SimpleValue::Num(NumKind::Natural(1))); |
91 | | /// map.insert("y".to_string(), SimpleValue::Num(NumKind::Natural(2))); |
92 | | /// assert_eq!(value, SimpleValue::Record(map)); |
93 | | /// # Ok(()) |
94 | | /// # } |
95 | | /// ``` |
96 | | /// |
97 | | /// [`from_str()`]: crate::from_str() |
98 | | /// [`from_file()`]: crate::from_file() |
99 | | /// [`from_simple_value()`]: crate::from_simple_value() |
100 | | #[derive(Debug, Clone, PartialEq, Eq)] |
101 | | pub enum SimpleValue { |
102 | | /// Numbers and booleans - `True`, `1`, `+2`, `3.24` |
103 | | Num(NumKind), |
104 | | /// A string of text - `"Hello world!"` |
105 | | Text(String), |
106 | | /// An optional value - `Some e`, `None` |
107 | | Optional(Option<Box<SimpleValue>>), |
108 | | /// A list of values - `[a, b, c, d, e]` |
109 | | List(Vec<SimpleValue>), |
110 | | /// A record value - `{ k1 = v1, k2 = v2 }` |
111 | | Record(BTreeMap<String, SimpleValue>), |
112 | | /// A union value (both the name of the variant and the variant's value) - `Left e` |
113 | | Union(String, Option<Box<SimpleValue>>), |
114 | | } |
115 | | |
116 | | /// The type of a value that can be decoded by `serde_dhall`, e.g. `{ x: Bool, y: List Natural }`. |
117 | | /// |
118 | | /// A `SimpleType` is used when deserializing values to ensure they are of the expected type. |
119 | | /// Rather than letting `serde` handle potential type mismatches, this uses the type-checking |
120 | | /// capabilities of Dhall to catch errors early and cleanly indicate in the user's code where the |
121 | | /// mismatch happened. |
122 | | /// |
123 | | /// You would typically not manipulate `SimpleType`s by hand but rather let Rust infer it for your |
124 | | /// datatype by deriving the [`StaticType`] trait, and using |
125 | | /// [`Deserializer::static_type_annotation`]. If you need to supply a `SimpleType` manually, you |
126 | | /// can either deserialize it like any other Dhall value, or construct it manually. |
127 | | /// |
128 | | /// [`Deserializer::static_type_annotation`]: crate::Deserializer::static_type_annotation() |
129 | | /// [`StaticType`]: crate::StaticType |
130 | | /// |
131 | | /// # Type correspondence |
132 | | /// |
133 | | /// The following Dhall types correspond to the following Rust types: |
134 | | /// |
135 | | /// Dhall | Rust |
136 | | /// -------|------ |
137 | | /// `Bool` | `bool` |
138 | | /// `Natural` | `u64`, `u32`, ... |
139 | | /// `Integer` | `i64`, `i32`, ... |
140 | | /// `Double` | `f64`, `f32`, ... |
141 | | /// `Text` | `String` |
142 | | /// `List T` | `Vec<T>` |
143 | | /// `Optional T` | `Option<T>` |
144 | | /// `{ x: T, y: U }` | structs |
145 | | /// `{ _1: T, _2: U }` | `(T, U)`, structs |
146 | | /// `{ x: T, y: T }` | `HashMap<String, T>`, structs |
147 | | /// `< x: T \| y: U >` | enums |
148 | | /// `Prelude.Map.Type Text T` | `HashMap<String, T>`, structs |
149 | | /// `T -> U` | unsupported |
150 | | /// `Prelude.JSON.Type` | unsupported |
151 | | /// `Prelude.Map.Type T U` | unsupported |
152 | | /// |
153 | | /// # Examples |
154 | | /// |
155 | | /// ```rust |
156 | | /// # fn main() -> serde_dhall::Result<()> { |
157 | | /// use serde_dhall::{SimpleType, StaticType}; |
158 | | /// |
159 | | /// #[derive(StaticType)] |
160 | | /// struct Foo { |
161 | | /// x: bool, |
162 | | /// y: Vec<u64>, |
163 | | /// } |
164 | | /// |
165 | | /// let ty: SimpleType = |
166 | | /// serde_dhall::from_str("{ x: Bool, y: List Natural }").parse()?; |
167 | | /// |
168 | | /// assert_eq!(Foo::static_type(), ty); |
169 | | /// # Ok(()) |
170 | | /// # } |
171 | | /// ``` |
172 | | /// |
173 | | /// ```rust |
174 | | /// # fn main() -> serde_dhall::Result<()> { |
175 | | /// use std::collections::HashMap; |
176 | | /// use serde_dhall::SimpleType; |
177 | | /// |
178 | | /// let ty: SimpleType = |
179 | | /// serde_dhall::from_str("{ x: Natural, y: Natural }").parse()?; |
180 | | /// |
181 | | /// let mut map = HashMap::new(); |
182 | | /// map.insert("x".to_string(), SimpleType::Natural); |
183 | | /// map.insert("y".to_string(), SimpleType::Natural); |
184 | | /// assert_eq!(ty, SimpleType::Record(map)); |
185 | | /// # Ok(()) |
186 | | /// # } |
187 | | /// ``` |
188 | | #[derive(Debug, Clone, PartialEq, Eq)] |
189 | | pub enum SimpleType { |
190 | | /// Corresponds to the Dhall type `Bool` |
191 | | Bool, |
192 | | /// Corresponds to the Dhall type `Natural` |
193 | | Natural, |
194 | | /// Corresponds to the Dhall type `Integer` |
195 | | Integer, |
196 | | /// Corresponds to the Dhall type `Double` |
197 | | Double, |
198 | | /// Corresponds to the Dhall type `Text` |
199 | | Text, |
200 | | /// Corresponds to the Dhall type `Optional T` |
201 | | Optional(Box<SimpleType>), |
202 | | /// Corresponds to the Dhall type `List T` |
203 | | List(Box<SimpleType>), |
204 | | /// Corresponds to the Dhall type `{ x : T, y : U }` |
205 | | Record(HashMap<String, SimpleType>), |
206 | | /// Corresponds to the Dhall type `< x : T | y : U >` |
207 | | Union(HashMap<String, Option<SimpleType>>), |
208 | | } |
209 | | |
210 | | impl Value { |
211 | 0 | pub(crate) fn from_nir_and_ty<'cx>( |
212 | 0 | cx: Ctxt<'cx>, |
213 | 0 | x: &Nir<'cx>, |
214 | 0 | ty: &Nir<'cx>, |
215 | 0 | ) -> Result<Self> { |
216 | 0 | Ok(if let Ok(val) = SimpleValue::from_nir(x) { |
217 | | // The type must be simple if the value is simple. |
218 | 0 | let ty = SimpleType::from_nir(ty).unwrap(); |
219 | 0 | Value { |
220 | 0 | kind: ValueKind::Val(val, Some(ty)), |
221 | 0 | } |
222 | 0 | } else if let Ok(ty) = SimpleType::from_nir(x) { |
223 | 0 | Value { |
224 | 0 | kind: ValueKind::Ty(ty), |
225 | 0 | } |
226 | | } else { |
227 | 0 | let expr = x.to_hir_noenv().to_expr(cx, Default::default()); |
228 | 0 | return Err(Error(ErrorKind::Deserialize(format!( |
229 | 0 | "this is neither a simple type nor a simple value: {}", |
230 | 0 | expr |
231 | 0 | )))); |
232 | | }) |
233 | 0 | } |
234 | | |
235 | | /// Converts a Value into a SimpleValue. |
236 | 0 | pub(crate) fn to_simple_value(&self) -> Option<SimpleValue> { |
237 | 0 | match &self.kind { |
238 | 0 | ValueKind::Val(val, _) => Some(val.clone()), |
239 | 0 | _ => None, |
240 | | } |
241 | 0 | } |
242 | | |
243 | | /// Converts a Value into a SimpleType. |
244 | 0 | pub(crate) fn to_simple_type(&self) -> Option<SimpleType> { |
245 | 0 | match &self.kind { |
246 | 0 | ValueKind::Ty(ty) => Some(ty.clone()), |
247 | 0 | _ => None, |
248 | | } |
249 | 0 | } |
250 | | |
251 | | /// Converts a value back to the corresponding AST expression. |
252 | 0 | pub(crate) fn to_expr(&self) -> Expr { |
253 | 0 | match &self.kind { |
254 | 0 | ValueKind::Val(val, ty) => val.to_expr(ty.as_ref()).unwrap(), |
255 | 0 | ValueKind::Ty(ty) => ty.to_expr(), |
256 | | } |
257 | 0 | } |
258 | | } |
259 | | |
260 | | #[derive(Debug)] |
261 | | struct NotSimpleValue; |
262 | | |
263 | | impl SimpleValue { |
264 | 0 | fn from_nir(nir: &Nir) -> StdResult<Self, NotSimpleValue> { |
265 | 0 | Ok(match nir.kind() { |
266 | 0 | NirKind::Num(lit) => SimpleValue::Num(lit.clone()), |
267 | 0 | NirKind::TextLit(x) => SimpleValue::Text( |
268 | 0 | x.as_text() |
269 | 0 | .expect("Normal form should ensure the text is a string"), |
270 | 0 | ), |
271 | 0 | NirKind::EmptyOptionalLit(_) => SimpleValue::Optional(None), |
272 | 0 | NirKind::NEOptionalLit(x) => { |
273 | 0 | SimpleValue::Optional(Some(Box::new(Self::from_nir(x)?))) |
274 | | } |
275 | 0 | NirKind::EmptyListLit(t) => { |
276 | | // Detect and handle the special records that make assoc maps |
277 | 0 | if let NirKind::RecordType(kts) = t.kind() { |
278 | 0 | if kts.len() == 2 |
279 | 0 | && kts.contains_key("mapKey") |
280 | 0 | && kts.contains_key("mapValue") |
281 | | { |
282 | 0 | return Ok(SimpleValue::Record(Default::default())); |
283 | 0 | } |
284 | 0 | } |
285 | 0 | SimpleValue::List(vec![]) |
286 | | } |
287 | 0 | NirKind::NEListLit(xs) => { |
288 | | // Detect and handle the special records that make assoc maps |
289 | 0 | if let NirKind::RecordLit(kvs) = xs[0].kind() { |
290 | 0 | if kvs.len() == 2 |
291 | 0 | && kvs.contains_key("mapKey") |
292 | 0 | && kvs.contains_key("mapValue") |
293 | | { |
294 | 0 | let convert_entry = |x: &Nir| match x.kind() { |
295 | 0 | NirKind::RecordLit(kvs) => { |
296 | 0 | let k = match kvs.get("mapKey").unwrap().kind() |
297 | | { |
298 | 0 | NirKind::TextLit(t) |
299 | 0 | if t.as_text().is_some() => |
300 | | { |
301 | 0 | t.as_text().unwrap() |
302 | | } |
303 | | // TODO |
304 | 0 | _ => panic!( |
305 | | "Expected `mapKey` to be a text \ |
306 | | literal" |
307 | | ), |
308 | | }; |
309 | 0 | let v = Self::from_nir( |
310 | 0 | kvs.get("mapValue").unwrap(), |
311 | 0 | )?; |
312 | 0 | Ok((k, v)) |
313 | | } |
314 | 0 | _ => unreachable!("Internal type error"), |
315 | 0 | }; |
316 | | return Ok(SimpleValue::Record( |
317 | 0 | xs.iter() |
318 | 0 | .map(convert_entry) |
319 | 0 | .collect::<StdResult<_, _>>()?, |
320 | | )); |
321 | 0 | } |
322 | 0 | } |
323 | | SimpleValue::List( |
324 | 0 | xs.iter() |
325 | 0 | .map(Self::from_nir) |
326 | 0 | .collect::<StdResult<_, _>>()?, |
327 | | ) |
328 | | } |
329 | 0 | NirKind::RecordLit(kvs) => SimpleValue::Record( |
330 | 0 | kvs.iter() |
331 | 0 | .map(|(k, v)| Ok((k.to_string(), Self::from_nir(v)?))) |
332 | 0 | .collect::<StdResult<_, _>>()?, |
333 | | ), |
334 | 0 | NirKind::UnionLit(field, x, _) => SimpleValue::Union( |
335 | 0 | field.into(), |
336 | 0 | Some(Box::new(Self::from_nir(x)?)), |
337 | | ), |
338 | 0 | NirKind::UnionConstructor(field, ty) |
339 | 0 | if ty.get(field).map(|f| f.is_some()) == Some(false) => |
340 | | { |
341 | 0 | SimpleValue::Union(field.into(), None) |
342 | | } |
343 | 0 | _ => return Err(NotSimpleValue), |
344 | | }) |
345 | 0 | } |
346 | | |
347 | | // Converts this to `Hir`, using the optional type annotation. Without the type, things like |
348 | | // empty lists and unions will fail to convert. |
349 | 0 | fn to_hir<'cx>(&self, ty: Option<&SimpleType>) -> Result<Hir<'cx>> { |
350 | | use SimpleType as T; |
351 | | use SimpleValue as V; |
352 | 0 | let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial); |
353 | 0 | let type_error = || { |
354 | 0 | Error(ErrorKind::Serialize(format!( |
355 | 0 | "expected a value of type {}, found {:?}", |
356 | 0 | ty.unwrap().to_expr(), |
357 | 0 | self |
358 | 0 | ))) |
359 | 0 | }; |
360 | 0 | let type_missing = || { |
361 | 0 | Error(ErrorKind::Serialize(format!( |
362 | 0 | "cannot serialize value without a type annotation: {:?}", |
363 | 0 | self |
364 | 0 | ))) |
365 | 0 | }; |
366 | 0 | let kind = match (self, ty) { |
367 | 0 | (V::Num(num @ NumKind::Bool(_)), Some(T::Bool)) |
368 | 0 | | (V::Num(num @ NumKind::Natural(_)), Some(T::Natural)) |
369 | 0 | | (V::Num(num @ NumKind::Integer(_)), Some(T::Integer)) |
370 | 0 | | (V::Num(num @ NumKind::Double(_)), Some(T::Double)) |
371 | 0 | | (V::Num(num), None) => ExprKind::Num(num.clone()), |
372 | 0 | (V::Text(v), Some(T::Text)) | (V::Text(v), None) => { |
373 | 0 | ExprKind::TextLit(v.clone().into()) |
374 | | } |
375 | | |
376 | 0 | (V::Optional(None), None) => return Err(type_missing()), |
377 | 0 | (V::Optional(None), Some(T::Optional(t))) => { |
378 | 0 | ExprKind::Op(OpKind::App( |
379 | 0 | hir(ExprKind::Builtin(Builtin::OptionalNone)), |
380 | 0 | t.to_hir(), |
381 | 0 | )) |
382 | | } |
383 | 0 | (V::Optional(Some(v)), None) => ExprKind::SomeLit(v.to_hir(None)?), |
384 | 0 | (V::Optional(Some(v)), Some(T::Optional(t))) => { |
385 | 0 | ExprKind::SomeLit(v.to_hir(Some(t))?) |
386 | | } |
387 | | |
388 | 0 | (V::List(v), None) if v.is_empty() => return Err(type_missing()), |
389 | 0 | (V::List(v), Some(T::List(t))) if v.is_empty() => { |
390 | 0 | ExprKind::EmptyListLit(hir(ExprKind::Op(OpKind::App( |
391 | 0 | hir(ExprKind::Builtin(Builtin::List)), |
392 | 0 | t.to_hir(), |
393 | 0 | )))) |
394 | | } |
395 | 0 | (V::List(v), None) => ExprKind::NEListLit( |
396 | 0 | v.iter().map(|v| v.to_hir(None)).collect::<Result<_>>()?, |
397 | | ), |
398 | 0 | (V::List(v), Some(T::List(t))) => ExprKind::NEListLit( |
399 | 0 | v.iter().map(|v| v.to_hir(Some(t))).collect::<Result<_>>()?, |
400 | | ), |
401 | | |
402 | 0 | (V::Record(v), None) => ExprKind::RecordLit( |
403 | 0 | v.iter() |
404 | 0 | .map(|(k, v)| Ok((k.clone().into(), v.to_hir(None)?))) |
405 | 0 | .collect::<Result<_>>()?, |
406 | | ), |
407 | 0 | (V::Record(v), Some(T::Record(t))) => ExprKind::RecordLit( |
408 | 0 | v.iter() |
409 | 0 | .map(|(k, v)| match t.get(k) { |
410 | 0 | Some(t) => Ok((k.clone().into(), v.to_hir(Some(t))?)), |
411 | 0 | None => Err(type_error()), |
412 | 0 | }) |
413 | 0 | .collect::<Result<_>>()?, |
414 | | ), |
415 | | |
416 | 0 | (V::Union(..), None) => return Err(type_missing()), |
417 | 0 | (V::Union(variant, Some(v)), Some(T::Union(t))) => { |
418 | 0 | match t.get(variant) { |
419 | 0 | Some(Some(variant_t)) => ExprKind::Op(OpKind::App( |
420 | 0 | hir(ExprKind::Op(OpKind::Field( |
421 | 0 | ty.unwrap().to_hir(), |
422 | 0 | variant.clone().into(), |
423 | 0 | ))), |
424 | 0 | v.to_hir(Some(variant_t))?, |
425 | | )), |
426 | 0 | _ => return Err(type_error()), |
427 | | } |
428 | | } |
429 | 0 | (V::Union(variant, None), Some(T::Union(t))) => { |
430 | 0 | match t.get(variant) { |
431 | 0 | Some(None) => ExprKind::Op(OpKind::Field( |
432 | 0 | ty.unwrap().to_hir(), |
433 | 0 | variant.clone().into(), |
434 | 0 | )), |
435 | 0 | _ => return Err(type_error()), |
436 | | } |
437 | | } |
438 | | |
439 | 0 | (_, Some(_)) => return Err(type_error()), |
440 | | }; |
441 | 0 | Ok(hir(kind)) |
442 | 0 | } |
443 | 0 | pub(crate) fn into_value(self, ty: Option<&SimpleType>) -> Result<Value> { |
444 | | // Check that the value is printable with the given type. |
445 | 0 | self.to_hir(ty)?; |
446 | 0 | Ok(Value { |
447 | 0 | kind: ValueKind::Val(self, ty.cloned()), |
448 | 0 | }) |
449 | 0 | } |
450 | | |
451 | | /// Converts back to the corresponding AST expression. |
452 | 0 | pub(crate) fn to_expr(&self, ty: Option<&SimpleType>) -> Result<Expr> { |
453 | 0 | Ctxt::with_new(|cx| { |
454 | 0 | Ok(self.to_hir(ty)?.to_expr(cx, Default::default())) |
455 | 0 | }) |
456 | 0 | } |
457 | | } |
458 | | |
459 | | #[derive(Debug)] |
460 | | struct NotSimpleType; |
461 | | |
462 | | impl SimpleType { |
463 | 0 | fn from_nir(nir: &Nir) -> StdResult<Self, NotSimpleType> { |
464 | 0 | Ok(match nir.kind() { |
465 | 0 | NirKind::BuiltinType(b) => match b { |
466 | 0 | Builtin::Bool => SimpleType::Bool, |
467 | 0 | Builtin::Natural => SimpleType::Natural, |
468 | 0 | Builtin::Integer => SimpleType::Integer, |
469 | 0 | Builtin::Double => SimpleType::Double, |
470 | 0 | Builtin::Text => SimpleType::Text, |
471 | 0 | _ => unreachable!(), |
472 | | }, |
473 | 0 | NirKind::OptionalType(t) => { |
474 | 0 | SimpleType::Optional(Box::new(Self::from_nir(t)?)) |
475 | | } |
476 | 0 | NirKind::ListType(t) => { |
477 | 0 | SimpleType::List(Box::new(Self::from_nir(t)?)) |
478 | | } |
479 | 0 | NirKind::RecordType(kts) => SimpleType::Record( |
480 | 0 | kts.iter() |
481 | 0 | .map(|(k, v)| Ok((k.into(), Self::from_nir(v)?))) |
482 | 0 | .collect::<StdResult<_, _>>()?, |
483 | | ), |
484 | 0 | NirKind::UnionType(kts) => SimpleType::Union( |
485 | 0 | kts.iter() |
486 | 0 | .map(|(k, v)| { |
487 | | Ok(( |
488 | 0 | k.into(), |
489 | 0 | v.as_ref().map(Self::from_nir).transpose()?, |
490 | | )) |
491 | 0 | }) |
492 | 0 | .collect::<StdResult<_, _>>()?, |
493 | | ), |
494 | 0 | _ => return Err(NotSimpleType), |
495 | | }) |
496 | 0 | } |
497 | | |
498 | 0 | pub(crate) fn to_hir<'cx>(&self) -> Hir<'cx> { |
499 | 0 | let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial); |
500 | 0 | hir(match self { |
501 | 0 | SimpleType::Bool => ExprKind::Builtin(Builtin::Bool), |
502 | 0 | SimpleType::Natural => ExprKind::Builtin(Builtin::Natural), |
503 | 0 | SimpleType::Integer => ExprKind::Builtin(Builtin::Integer), |
504 | 0 | SimpleType::Double => ExprKind::Builtin(Builtin::Double), |
505 | 0 | SimpleType::Text => ExprKind::Builtin(Builtin::Text), |
506 | 0 | SimpleType::Optional(t) => ExprKind::Op(OpKind::App( |
507 | 0 | hir(ExprKind::Builtin(Builtin::Optional)), |
508 | 0 | t.to_hir(), |
509 | 0 | )), |
510 | 0 | SimpleType::List(t) => ExprKind::Op(OpKind::App( |
511 | 0 | hir(ExprKind::Builtin(Builtin::List)), |
512 | 0 | t.to_hir(), |
513 | 0 | )), |
514 | 0 | SimpleType::Record(kts) => ExprKind::RecordType( |
515 | 0 | kts.iter() |
516 | 0 | .map(|(k, t)| (k.as_str().into(), t.to_hir())) |
517 | 0 | .collect(), |
518 | | ), |
519 | 0 | SimpleType::Union(kts) => ExprKind::UnionType( |
520 | 0 | kts.iter() |
521 | 0 | .map(|(k, t)| { |
522 | 0 | (k.as_str().into(), t.as_ref().map(|t| t.to_hir())) |
523 | 0 | }) |
524 | 0 | .collect(), |
525 | | ), |
526 | | }) |
527 | 0 | } |
528 | | |
529 | | /// Converts back to the corresponding AST expression. |
530 | 0 | pub(crate) fn to_expr(&self) -> Expr { |
531 | 0 | Ctxt::with_new(|cx| self.to_hir().to_expr(cx, Default::default())) |
532 | 0 | } |
533 | | } |
534 | | |
535 | | impl crate::deserialize::Sealed for Value {} |
536 | | impl crate::deserialize::Sealed for SimpleType {} |
537 | | impl crate::serialize::Sealed for Value {} |
538 | | impl crate::serialize::Sealed for SimpleType {} |
539 | | |
540 | | impl FromDhall for Value { |
541 | 0 | fn from_dhall(v: &Value) -> Result<Self> { |
542 | 0 | Ok(v.clone()) |
543 | 0 | } |
544 | | } |
545 | | impl FromDhall for SimpleType { |
546 | 0 | fn from_dhall(v: &Value) -> Result<Self> { |
547 | 0 | v.to_simple_type().ok_or_else(|| { |
548 | 0 | Error(ErrorKind::Deserialize(format!( |
549 | 0 | "this cannot be deserialized into a simple type: {}", |
550 | 0 | v |
551 | 0 | ))) |
552 | 0 | }) |
553 | 0 | } |
554 | | } |
555 | | impl ToDhall for Value { |
556 | 0 | fn to_dhall(&self, _ty: Option<&SimpleType>) -> Result<Value> { |
557 | 0 | Ok(self.clone()) |
558 | 0 | } |
559 | | } |
560 | | impl ToDhall for SimpleType { |
561 | 0 | fn to_dhall(&self, _ty: Option<&SimpleType>) -> Result<Value> { |
562 | 0 | Ok(Value { |
563 | 0 | kind: ValueKind::Ty(self.clone()), |
564 | 0 | }) |
565 | 0 | } |
566 | | } |
567 | | |
568 | | impl Eq for ValueKind {} |
569 | | impl PartialEq for ValueKind { |
570 | 0 | fn eq(&self, other: &Self) -> bool { |
571 | | use ValueKind::*; |
572 | 0 | match (self, other) { |
573 | 0 | (Val(a, _), Val(b, _)) => a == b, |
574 | 0 | (Ty(a), Ty(b)) => a == b, |
575 | 0 | _ => false, |
576 | | } |
577 | 0 | } |
578 | | } |
579 | | impl std::fmt::Display for Value { |
580 | 0 | fn fmt( |
581 | 0 | &self, |
582 | 0 | f: &mut std::fmt::Formatter, |
583 | 0 | ) -> StdResult<(), std::fmt::Error> { |
584 | 0 | self.to_expr().fmt(f) |
585 | 0 | } |
586 | | } |
587 | | |
588 | | impl std::fmt::Display for SimpleType { |
589 | 0 | fn fmt( |
590 | 0 | &self, |
591 | 0 | f: &mut std::fmt::Formatter, |
592 | 0 | ) -> StdResult<(), std::fmt::Error> { |
593 | 0 | self.to_expr().fmt(f) |
594 | 0 | } |
595 | | } |
596 | | |
597 | | #[test] |
598 | | fn test_display_simpletype() { |
599 | | use SimpleType::*; |
600 | | let ty = List(Box::new(Optional(Box::new(Natural)))); |
601 | | assert_eq!(ty.to_string(), "List (Optional Natural)".to_string()) |
602 | | } |
603 | | |
604 | | #[test] |
605 | | fn test_display_value() { |
606 | | use SimpleType::*; |
607 | | let ty = List(Box::new(Optional(Box::new(Natural)))); |
608 | | let val = SimpleValue::List(vec![]); |
609 | | let val = Value { |
610 | | kind: ValueKind::Val(val, Some(ty)), |
611 | | }; |
612 | | assert_eq!(val.to_string(), "[] : List (Optional Natural)".to_string()) |
613 | | } |