From fa89e9cb319b353332c9e835944e7f86a6604c42 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 18 Mar 2020 21:37:14 +0000 Subject: Move Value, SimpleValue and SimpleType to serde --- serde_dhall/src/simple.rs | 180 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 171 insertions(+), 9 deletions(-) (limited to 'serde_dhall/src/simple.rs') diff --git a/serde_dhall/src/simple.rs b/serde_dhall/src/simple.rs index 93364a0..0b322ae 100644 --- a/serde_dhall/src/simple.rs +++ b/serde_dhall/src/simple.rs @@ -1,25 +1,62 @@ -use super::Error; -use dhall::{STyKind, SimpleType, SimpleValue}; +use std::collections::BTreeMap; + +use dhall::semantics::{Hir, HirKind, Nir, NirKind}; +use dhall::syntax::{Builtin, ExprKind, NumKind, Span}; + +use crate::Error; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SimpleValue { + kind: Box, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SValKind { + Num(NumKind), + Text(String), + Optional(Option), + List(Vec), + Record(BTreeMap), + Union(String, Option), +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SimpleType { + kind: Box, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum STyKind { + Bool, + Natural, + Integer, + Double, + Text, + Optional(SimpleType), + List(SimpleType), + Record(BTreeMap), + Union(BTreeMap>), +} /// A Dhall value. This is a wrapper around [`dhall::SimpleValue`]. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Value(SimpleValue); +/// A Dhall type. This is a wrapper around [`dhall::SimpleType`]. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Type(SimpleType); + impl Value { pub fn into_simple_value(self) -> SimpleValue { self.0 } } -/// A Dhall type. This is a wrapper around [`dhall::SimpleType`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Type(SimpleType); - impl Type { pub fn into_simple_type(self) -> SimpleType { self.0 } - pub fn to_dhall_value(&self) -> dhall::Value { + pub fn to_value(&self) -> crate::Value { self.0.to_value() } @@ -52,10 +89,135 @@ impl Type { } } +impl SimpleValue { + pub fn new(kind: SValKind) -> Self { + SimpleValue { + kind: Box::new(kind), + } + } + pub fn from_nir(nir: &Nir) -> Option { + Some(SimpleValue::new(match nir.kind() { + NirKind::Num(lit) => SValKind::Num(lit.clone()), + NirKind::TextLit(x) => SValKind::Text( + x.as_text() + .expect("Normal form should ensure the text is a string"), + ), + NirKind::EmptyOptionalLit(_) => SValKind::Optional(None), + NirKind::NEOptionalLit(x) => { + SValKind::Optional(Some(Self::from_nir(x)?)) + } + NirKind::EmptyListLit(_) => SValKind::List(vec![]), + NirKind::NEListLit(xs) => SValKind::List( + xs.iter() + .map(|v| Self::from_nir(v)) + .collect::>()?, + ), + NirKind::RecordLit(kvs) => SValKind::Record( + kvs.iter() + .map(|(k, v)| Some((k.into(), Self::from_nir(v)?))) + .collect::>()?, + ), + NirKind::UnionLit(field, x, _) => { + SValKind::Union(field.into(), Some(Self::from_nir(x)?)) + } + NirKind::UnionConstructor(field, ty) + if ty.get(field).map(|f| f.is_some()) == Some(false) => + { + SValKind::Union(field.into(), None) + } + _ => return None, + })) + } + + pub fn kind(&self) -> &SValKind { + self.kind.as_ref() + } +} + +impl SimpleType { + pub fn new(kind: STyKind) -> Self { + SimpleType { + kind: Box::new(kind), + } + } + pub fn from_nir(nir: &Nir) -> Option { + Some(SimpleType::new(match nir.kind() { + NirKind::BuiltinType(b) => match b { + Builtin::Bool => STyKind::Bool, + Builtin::Natural => STyKind::Natural, + Builtin::Integer => STyKind::Integer, + Builtin::Double => STyKind::Double, + Builtin::Text => STyKind::Text, + _ => unreachable!(), + }, + NirKind::OptionalType(t) => STyKind::Optional(Self::from_nir(t)?), + NirKind::ListType(t) => STyKind::List(Self::from_nir(t)?), + NirKind::RecordType(kts) => STyKind::Record( + kts.iter() + .map(|(k, v)| Some((k.into(), Self::from_nir(v)?))) + .collect::>()?, + ), + NirKind::UnionType(kts) => STyKind::Union( + kts.iter() + .map(|(k, v)| { + Some(( + k.into(), + v.as_ref() + .map(|v| Ok(Self::from_nir(v)?)) + .transpose()?, + )) + }) + .collect::>()?, + ), + _ => return None, + })) + } + + pub fn kind(&self) -> &STyKind { + self.kind.as_ref() + } + pub fn to_value(&self) -> crate::Value { + crate::Value { + hir: self.to_hir(), + as_simple_val: None, + as_simple_ty: Some(self.clone()), + } + } + pub fn to_hir(&self) -> Hir { + let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial); + hir(match self.kind() { + STyKind::Bool => ExprKind::Builtin(Builtin::Bool), + STyKind::Natural => ExprKind::Builtin(Builtin::Natural), + STyKind::Integer => ExprKind::Builtin(Builtin::Integer), + STyKind::Double => ExprKind::Builtin(Builtin::Double), + STyKind::Text => ExprKind::Builtin(Builtin::Text), + STyKind::Optional(t) => ExprKind::App( + hir(ExprKind::Builtin(Builtin::Optional)), + t.to_hir(), + ), + STyKind::List(t) => { + ExprKind::App(hir(ExprKind::Builtin(Builtin::List)), t.to_hir()) + } + STyKind::Record(kts) => ExprKind::RecordType( + kts.into_iter() + .map(|(k, t)| (k.as_str().into(), t.to_hir())) + .collect(), + ), + STyKind::Union(kts) => ExprKind::UnionType( + kts.into_iter() + .map(|(k, t)| { + (k.as_str().into(), t.as_ref().map(|t| t.to_hir())) + }) + .collect(), + ), + }) + } +} + impl super::sealed::Sealed for Value {} impl super::Deserialize for Value { - fn from_dhall(v: &dhall::Value) -> super::Result { + fn from_dhall(v: &crate::Value) -> super::Result { let sval = v.to_simple_value().ok_or_else(|| { Error::Deserialize(format!( "this cannot be deserialized into a simple type: {}", @@ -69,7 +231,7 @@ impl super::Deserialize for Value { impl super::sealed::Sealed for Type {} impl super::Deserialize for Type { - fn from_dhall(v: &dhall::Value) -> super::Result { + fn from_dhall(v: &crate::Value) -> super::Result { let sty = v.to_simple_type().ok_or_else(|| { Error::Deserialize(format!( "this cannot be deserialized into a simple type: {}", -- cgit v1.2.3