diff options
-rw-r--r-- | dhall/src/lib.rs | 6 | ||||
-rw-r--r-- | dhall/src/semantics/nze/nir.rs | 48 | ||||
-rw-r--r-- | dhall/src/simple.rs | 52 | ||||
-rw-r--r-- | serde_dhall/src/lib.rs | 61 | ||||
-rw-r--r-- | serde_dhall/src/static_type.rs | 8 |
5 files changed, 138 insertions, 37 deletions
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index 0be6db3..25196ba 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -30,7 +30,7 @@ pub type ParsedExpr = Expr; pub type DecodedExpr = Expr; pub type ResolvedExpr = Expr; pub type NormalizedExpr = Expr; -pub use crate::simple::{SValKind, SimpleValue}; +pub use crate::simple::{STyKind, SValKind, SimpleType, SimpleValue}; #[derive(Debug, Clone)] pub struct Parsed(ParsedExpr, ImportLocation); @@ -146,6 +146,10 @@ impl Normalized { pub fn to_simple_value(&self) -> Result<SimpleValue, Expr> { self.0.to_simple_value().ok_or_else(|| self.to_expr()) } + /// Converts a value into a SimpleType. + pub fn to_simple_type(&self) -> Result<SimpleType, Expr> { + self.0.to_simple_type().ok_or_else(|| self.to_expr()) + } /// Converts a value back to the corresponding Hir expression. pub(crate) fn to_hir(&self) -> Hir { self.0.to_hir_noenv() diff --git a/dhall/src/semantics/nze/nir.rs b/dhall/src/semantics/nze/nir.rs index 9e3644c..4615b39 100644 --- a/dhall/src/semantics/nze/nir.rs +++ b/dhall/src/semantics/nze/nir.rs @@ -11,7 +11,7 @@ use crate::syntax::{ Span, }; use crate::{NormalizedExpr, ToExprOptions}; -use crate::{SValKind, SimpleValue}; +use crate::{STyKind, SValKind, SimpleType, SimpleValue}; /// Stores a possibly unevaluated value. Gets (partially) normalized on-demand, sharing computation /// automatically. Uses a Rc<RefCell> to share computation. @@ -176,6 +176,52 @@ impl Nir { _ => return None, })) } + pub(crate) fn to_simple_type(&self) -> Option<SimpleType> { + Some(SimpleType::new(match self.kind() { + NirKind::AppliedBuiltin(BuiltinClosure { b, args, .. }) + if args.is_empty() => + { + match b { + Builtin::Bool => STyKind::Bool, + Builtin::Natural => STyKind::Natural, + Builtin::Integer => STyKind::Integer, + Builtin::Double => STyKind::Double, + Builtin::Text => STyKind::Text, + _ => return None, + } + } + NirKind::AppliedBuiltin(BuiltinClosure { + b: Builtin::Optional, + args, + .. + }) if args.len() == 1 => { + STyKind::Optional(args[0].to_simple_type()?) + } + NirKind::AppliedBuiltin(BuiltinClosure { + b: Builtin::List, + args, + .. + }) if args.len() == 1 => STyKind::List(args[0].to_simple_type()?), + NirKind::RecordType(kts) => STyKind::Record( + kts.iter() + .map(|(k, v)| Some((k.into(), v.to_simple_type()?))) + .collect::<Option<_>>()?, + ), + NirKind::UnionType(kts) => STyKind::Union( + kts.iter() + .map(|(k, v)| { + Some(( + k.into(), + v.as_ref() + .map(|v| Ok(v.to_simple_type()?)) + .transpose()?, + )) + }) + .collect::<Option<_>>()?, + ), + _ => return None, + })) + } pub(crate) fn normalize(&self) { self.0.normalize() diff --git a/dhall/src/simple.rs b/dhall/src/simple.rs index 6457291..9d3846e 100644 --- a/dhall/src/simple.rs +++ b/dhall/src/simple.rs @@ -1,6 +1,7 @@ use std::collections::BTreeMap; -use crate::syntax::LitKind; +use crate::syntax::{Builtin, LitKind}; +use crate::Normalized; #[derive(Debug, Clone, PartialEq, Eq)] pub struct SimpleValue { @@ -17,6 +18,24 @@ pub enum SValKind { Text(String), } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SimpleType { + kind: Box<STyKind>, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum STyKind { + Bool, + Natural, + Integer, + Double, + Text, + Optional(SimpleType), + List(SimpleType), + Record(BTreeMap<String, SimpleType>), + Union(BTreeMap<String, Option<SimpleType>>), +} + impl SimpleValue { pub(crate) fn new(kind: SValKind) -> Self { SimpleValue { @@ -27,3 +46,34 @@ impl SimpleValue { self.kind.as_ref() } } + +impl SimpleType { + pub fn new(kind: STyKind) -> Self { + SimpleType { + kind: Box::new(kind), + } + } + pub fn kind(&self) -> &STyKind { + self.kind.as_ref() + } + pub fn into_normalized(self) -> Normalized { + match *self.kind { + STyKind::Bool => Normalized::make_builtin_type(Builtin::Bool), + STyKind::Natural => Normalized::make_builtin_type(Builtin::Natural), + STyKind::Integer => Normalized::make_builtin_type(Builtin::Integer), + STyKind::Double => Normalized::make_builtin_type(Builtin::Double), + STyKind::Text => Normalized::make_builtin_type(Builtin::Text), + STyKind::Optional(t) => { + Normalized::make_optional_type(t.into_normalized()) + } + STyKind::List(t) => Normalized::make_list_type(t.into_normalized()), + STyKind::Record(kts) => Normalized::make_record_type( + kts.into_iter().map(|(k, t)| (k, t.into_normalized())), + ), + STyKind::Union(kts) => Normalized::make_union_type( + kts.into_iter() + .map(|(k, t)| (k, t.map(|t| t.into_normalized()))), + ), + } + } +} diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs index 5f386e3..d019238 100644 --- a/serde_dhall/src/lib.rs +++ b/serde_dhall/src/lib.rs @@ -183,7 +183,7 @@ pub use value::Value; // A Dhall value. #[doc(hidden)] pub mod value { - use dhall::{Normalized, NormalizedExpr, Parsed, SimpleValue}; + use dhall::{Normalized, NormalizedExpr, Parsed, SimpleType, SimpleValue}; use super::de::Error; use super::Type; @@ -203,7 +203,7 @@ pub mod value { let resolved = Parsed::parse_str(s)?.resolve()?; let typed = match ty { None => resolved.typecheck()?, - Some(t) => resolved.typecheck_with(t.as_normalized())?, + Some(t) => resolved.typecheck_with(&t.to_normalized())?, }; Ok(Value(typed.normalize())) } @@ -212,6 +212,11 @@ pub mod value { ) -> Result<SimpleValue, NormalizedExpr> { self.0.to_simple_value() } + pub(crate) fn to_simple_type( + &self, + ) -> Result<SimpleType, NormalizedExpr> { + self.0.to_simple_type() + } } impl super::de::sealed::Sealed for Value {} @@ -226,56 +231,46 @@ pub mod value { // A Dhall type. #[doc(hidden)] pub mod ty { - use dhall::syntax::Builtin; - use dhall::{Normalized, Parsed}; + use dhall::{Normalized, STyKind, SimpleType}; use super::de::Error; - /// A Dhall value + /// A Dhall type #[derive(Debug, Clone, PartialEq, Eq)] - pub struct Type(Normalized); + pub struct Type(SimpleType); impl Type { - pub fn from_str(s: &str, ty: Option<&Type>) -> super::de::Result<Self> { - Type::from_str_using_dhall_error_type(s, ty).map_err(Error::Dhall) - } - fn from_str_using_dhall_error_type( - s: &str, - ty: Option<&Type>, - ) -> dhall::error::Result<Self> { - let resolved = Parsed::parse_str(s)?.resolve()?; - let typed = match ty { - None => resolved.typecheck()?, - Some(t) => resolved.typecheck_with(t.as_normalized())?, - }; - Ok(Type(typed.normalize())) - } - pub(crate) fn as_normalized(&self) -> &Normalized { - &self.0 + pub(crate) fn to_normalized(&self) -> Normalized { + self.0.clone().into_normalized() } - pub(crate) fn make_builtin_type(b: Builtin) -> Self { - Type(Normalized::make_builtin_type(b)) + pub(crate) fn from_simple_type(ty: SimpleType) -> Self { + Type(ty) + } + pub(crate) fn from_stykind(k: STyKind) -> Self { + Type(SimpleType::new(k)) } pub(crate) fn make_optional_type(t: Type) -> Self { - Type(Normalized::make_optional_type(t.0)) + Type::from_stykind(STyKind::Optional(t.0)) } pub(crate) fn make_list_type(t: Type) -> Self { - Type(Normalized::make_list_type(t.0)) + Type::from_stykind(STyKind::List(t.0)) } // Made public for the StaticType derive macro #[doc(hidden)] pub fn make_record_type( kts: impl Iterator<Item = (String, Type)>, ) -> Self { - Type(Normalized::make_record_type(kts.map(|(k, t)| (k, t.0)))) + Type::from_stykind(STyKind::Record( + kts.map(|(k, t)| (k, t.0)).collect(), + )) } #[doc(hidden)] pub fn make_union_type( kts: impl Iterator<Item = (String, Option<Type>)>, ) -> Self { - Type(Normalized::make_union_type( - kts.map(|(k, t)| (k, t.map(|t| t.0))), + Type::from_stykind(STyKind::Union( + kts.map(|(k, t)| (k, t.map(|t| t.0))).collect(), )) } } @@ -284,7 +279,13 @@ pub mod ty { impl super::de::Deserialize for Type { fn from_dhall(v: &super::Value) -> super::de::Result<Self> { - Ok(Type(v.0.clone())) + let sty = v.to_simple_type().map_err(|expr| { + Error::Deserialize(format!( + "this cannot be deserialized into a simple type: {}", + expr + )) + })?; + Ok(Type(sty)) } } } diff --git a/serde_dhall/src/static_type.rs b/serde_dhall/src/static_type.rs index 921b296..bc5f366 100644 --- a/serde_dhall/src/static_type.rs +++ b/serde_dhall/src/static_type.rs @@ -1,4 +1,4 @@ -use dhall::syntax::Builtin; +use dhall::{STyKind, SimpleType}; use crate::Type; @@ -18,10 +18,10 @@ pub trait StaticType { } macro_rules! derive_builtin { - ($ty:ty, $builtin:ident) => { - impl StaticType for $ty { + ($rust_ty:ty, $dhall_ty:ident) => { + impl StaticType for $rust_ty { fn static_type() -> Type { - Type::make_builtin_type(Builtin::$builtin) + Type::from_simple_type(SimpleType::new(STyKind::$dhall_ty)) } } }; |