summaryrefslogtreecommitdiff
path: root/serde_dhall/src/value.rs
diff options
context:
space:
mode:
authorNadrieril2020-10-28 21:45:42 +0000
committerNadrieril2020-10-28 22:52:41 +0000
commit3b728aff86a086f71f013b77a715c33748d9f6a8 (patch)
tree7c1ceba27495481b766b4ea84601d7381530f5c2 /serde_dhall/src/value.rs
parente070270c3f1f10d46281ed7751ff95e15092e7f4 (diff)
Make type annotation optional to allow serializing SimpleValue
Diffstat (limited to 'serde_dhall/src/value.rs')
-rw-r--r--serde_dhall/src/value.rs140
1 files changed, 75 insertions, 65 deletions
diff --git a/serde_dhall/src/value.rs b/serde_dhall/src/value.rs
index ca05658..50c12bd 100644
--- a/serde_dhall/src/value.rs
+++ b/serde_dhall/src/value.rs
@@ -293,87 +293,103 @@ impl SimpleValue {
})
}
- fn to_hir(&self, ty: &SimpleType) -> Result<Hir> {
+ // Converts this to `Hir`, using the optional type annotation. Without the type, things like
+ // empty lists and unions will fail to convert.
+ fn to_hir(&self, ty: Option<&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 type_error = || {
+ Error(ErrorKind::Serialize(format!(
+ "expected a value of type {}, found {:?}",
+ ty.unwrap().to_hir().to_expr(Default::default()),
+ self
+ )))
+ };
+ let type_missing = || {
+ Error(ErrorKind::Serialize(format!(
+ "cannot serialize value without a type annotation: {:?}",
+ self
+ )))
+ };
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::Num(num @ NumKind::Bool(_)), Some(T::Bool))
+ | (V::Num(num @ NumKind::Natural(_)), Some(T::Natural))
+ | (V::Num(num @ NumKind::Integer(_)), Some(T::Integer))
+ | (V::Num(num @ NumKind::Double(_)), Some(T::Double))
+ | (V::Num(num), None) => ExprKind::Num(num.clone()),
+ (V::Text(v), Some(T::Text)) | (V::Text(v), None) => {
+ ExprKind::TextLit(v.clone().into())
}
- (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::Optional(None), None) => return Err(type_missing()),
+ (V::Optional(None), Some(T::Optional(t))) => {
+ ExprKind::Op(OpKind::App(
+ hir(ExprKind::Builtin(Builtin::OptionalNone)),
+ t.to_hir(),
+ ))
+ }
+ (V::Optional(Some(v)), None) => ExprKind::SomeLit(v.to_hir(None)?),
+ (V::Optional(Some(v)), Some(T::Optional(t))) => {
+ ExprKind::SomeLit(v.to_hir(Some(t))?)
}
- (V::List(v), T::List(t)) if v.is_empty() => {
+
+ (V::List(v), None) if v.is_empty() => return Err(type_missing()),
+ (V::List(v), Some(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::List(v), None) => ExprKind::NEListLit(
+ v.iter().map(|v| v.to_hir(None)).collect::<Result<_>>()?,
+ ),
+ (V::List(v), Some(T::List(t))) => ExprKind::NEListLit(
+ v.iter().map(|v| v.to_hir(Some(t))).collect::<Result<_>>()?,
+ ),
+
+ (V::Record(v), None) => ExprKind::RecordLit(
+ v.iter()
+ .map(|(k, v)| Ok((k.clone().into(), v.to_hir(None)?)))
+ .collect::<Result<_>>()?,
),
- (V::Record(v), T::Record(t)) => ExprKind::RecordLit(
+ (V::Record(v), Some(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
- ))),
+ Some(t) => Ok((k.clone().into(), v.to_hir(Some(t))?)),
+ None => Err(type_error()),
})
.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(..), None) => return Err(type_missing()),
+ (V::Union(variant, Some(v)), Some(T::Union(t))) => {
+ match t.get(variant) {
+ Some(Some(variant_t)) => ExprKind::Op(OpKind::App(
+ hir(ExprKind::Op(OpKind::Field(
+ ty.unwrap().to_hir(),
+ variant.clone().into(),
+ ))),
+ v.to_hir(Some(variant_t))?,
+ )),
+ _ => return Err(type_error()),
}
- },
- (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
- )))
+ }
+ (V::Union(variant, None), Some(T::Union(t))) => {
+ match t.get(variant) {
+ Some(None) => ExprKind::Op(OpKind::Field(
+ ty.unwrap().to_hir(),
+ variant.clone().into(),
+ )),
+ _ => return Err(type_error()),
}
- },
- _ => {
- return Err(type_error(format!(
- "expected a value of type {}, found {:?}",
- ty.to_hir().to_expr(Default::default()),
- self
- )))
}
+
+ (_, Some(_)) => return Err(type_error()),
};
Ok(hir(kind))
}
- pub(crate) fn into_value(self, ty: &SimpleType) -> Result<Value> {
+ pub(crate) fn into_value(self, ty: Option<&SimpleType>) -> Result<Value> {
Ok(Value {
hir: self.to_hir(ty)?,
as_simple_val: Some(self),
@@ -467,7 +483,6 @@ impl 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> {
@@ -485,15 +500,10 @@ impl FromDhall for SimpleType {
}
}
impl ToDhall for Value {
- fn to_dhall(&self, _ty: &SimpleType) -> Result<Value> {
+ fn to_dhall(&self, _ty: Option<&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 {