summaryrefslogtreecommitdiff
path: root/serde_dhall/src/value.rs
diff options
context:
space:
mode:
authorNadrieril2020-05-10 22:09:43 +0100
committerNadrieril2020-10-28 22:52:41 +0000
commite070270c3f1f10d46281ed7751ff95e15092e7f4 (patch)
tree46c22c75f209c5112030f3db6609ed64ff4888d3 /serde_dhall/src/value.rs
parent5f3ca811f09dcf6f09fb9b60fcd2664d06762f39 (diff)
Implement serialization
Diffstat (limited to '')
-rw-r--r--serde_dhall/src/value.rs106
1 files changed, 103 insertions, 3 deletions
diff --git a/serde_dhall/src/value.rs b/serde_dhall/src/value.rs
index d7116d9..ca05658 100644
--- a/serde_dhall/src/value.rs
+++ b/serde_dhall/src/value.rs
@@ -6,7 +6,7 @@ use dhall::semantics::{Hir, HirKind, Nir, NirKind};
pub use dhall::syntax::NumKind;
use dhall::syntax::{Expr, ExprKind, Span};
-use crate::{Error, ErrorKind, FromDhall, Result, Sealed};
+use crate::{Error, ErrorKind, FromDhall, Result, ToDhall};
#[doc(hidden)]
/// An arbitrary Dhall value.
@@ -292,6 +292,94 @@ impl SimpleValue {
_ => return None,
})
}
+
+ fn to_hir(&self, ty: &SimpleType) -> Result<Hir> {
+ use SimpleType as T;
+ use SimpleValue as V;
+ let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial);
+ let type_error = |msg| Error(ErrorKind::Serialize(msg));
+ let kind = match (self, ty) {
+ (V::Num(num @ NumKind::Bool(_)), T::Bool)
+ | (V::Num(num @ NumKind::Natural(_)), T::Natural)
+ | (V::Num(num @ NumKind::Integer(_)), T::Integer)
+ | (V::Num(num @ NumKind::Double(_)), T::Double) => {
+ ExprKind::Num(num.clone())
+ }
+ (V::Text(v), T::Text) => ExprKind::TextLit(v.clone().into()),
+ (V::Optional(None), T::Optional(t)) => ExprKind::Op(OpKind::App(
+ hir(ExprKind::Builtin(Builtin::OptionalNone)),
+ t.to_hir(),
+ )),
+ (V::Optional(Some(v)), T::Optional(t)) => {
+ ExprKind::SomeLit(v.to_hir(t)?)
+ }
+ (V::List(v), T::List(t)) if v.is_empty() => {
+ ExprKind::EmptyListLit(hir(ExprKind::Op(OpKind::App(
+ hir(ExprKind::Builtin(Builtin::List)),
+ t.to_hir(),
+ ))))
+ }
+ (V::List(v), T::List(t)) => ExprKind::NEListLit(
+ v.iter().map(|v| v.to_hir(t)).collect::<Result<_>>()?,
+ ),
+ (V::Record(v), T::Record(t)) => ExprKind::RecordLit(
+ v.iter()
+ .map(|(k, v)| match t.get(k) {
+ Some(t) => Ok((k.clone().into(), v.to_hir(t)?)),
+ None => Err(type_error(format!(
+ "expected a value of type {}, found {:?}",
+ ty.to_hir().to_expr(Default::default()),
+ self
+ ))),
+ })
+ .collect::<Result<_>>()?,
+ ),
+ (V::Union(variant, Some(v)), T::Union(t)) => match t.get(variant) {
+ Some(Some(variant_t)) => ExprKind::Op(OpKind::App(
+ hir(ExprKind::Op(OpKind::Field(
+ ty.to_hir(),
+ variant.clone().into(),
+ ))),
+ v.to_hir(variant_t)?,
+ )),
+ _ => {
+ return Err(type_error(format!(
+ "expected a value of type {}, found {:?}",
+ ty.to_hir().to_expr(Default::default()),
+ self
+ )))
+ }
+ },
+ (V::Union(variant, None), T::Union(t)) => match t.get(variant) {
+ Some(None) => ExprKind::Op(OpKind::Field(
+ ty.to_hir(),
+ variant.clone().into(),
+ )),
+ _ => {
+ return Err(type_error(format!(
+ "expected a value of type {}, found {:?}",
+ ty.to_hir().to_expr(Default::default()),
+ self
+ )))
+ }
+ },
+ _ => {
+ return Err(type_error(format!(
+ "expected a value of type {}, found {:?}",
+ ty.to_hir().to_expr(Default::default()),
+ self
+ )))
+ }
+ };
+ Ok(hir(kind))
+ }
+ pub(crate) fn into_value(self, ty: &SimpleType) -> Result<Value> {
+ Ok(Value {
+ hir: self.to_hir(ty)?,
+ as_simple_val: Some(self),
+ as_simple_ty: None,
+ })
+ }
}
impl SimpleType {
@@ -376,8 +464,10 @@ impl SimpleType {
}
}
-impl Sealed for Value {}
-impl Sealed for SimpleType {}
+impl crate::deserialize::Sealed for Value {}
+impl crate::deserialize::Sealed for SimpleType {}
+impl crate::serialize::Sealed for Value {}
+impl crate::serialize::Sealed for SimpleValue {}
impl FromDhall for Value {
fn from_dhall(v: &Value) -> Result<Self> {
@@ -394,6 +484,16 @@ impl FromDhall for SimpleType {
})
}
}
+impl ToDhall for Value {
+ fn to_dhall(&self, _ty: &SimpleType) -> Result<Value> {
+ Ok(self.clone())
+ }
+}
+impl ToDhall for SimpleValue {
+ fn to_dhall(&self, ty: &SimpleType) -> Result<Value> {
+ self.clone().into_value(ty)
+ }
+}
impl Eq for Value {}
impl PartialEq for Value {