From 4e11e882b7d064e9ddf997f9a465206cf6e471aa Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 8 Mar 2020 17:36:51 +0000 Subject: Split serde_dhall::Value to separate values from types --- README.md | 4 ++ dhall_proc_macros/src/derive.rs | 6 +-- serde_dhall/src/lib.rs | 86 +++++++++++++++++++++++++++++------------ serde_dhall/src/static_type.rs | 26 ++++++------- serde_dhall/tests/traits.rs | 4 +- test.dhall | 4 ++ 6 files changed, 88 insertions(+), 42 deletions(-) create mode 100644 test.dhall diff --git a/README.md b/README.md index ffd55ef..1bcf558 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,10 @@ same name as the corresponding test. ## Changelog +#### [???] + +- Breaking change: use `serde_dhall::Type` type for type-checking instead of `serde_dhall::Value` + #### [0.4.0] - `dhall` now uses the stable Rust toolchain ! diff --git a/dhall_proc_macros/src/derive.rs b/dhall_proc_macros/src/derive.rs index 48626a0..3a4f1aa 100644 --- a/dhall_proc_macros/src/derive.rs +++ b/dhall_proc_macros/src/derive.rs @@ -52,7 +52,7 @@ fn derive_for_struct( let ty = static_type(ty); quote!( (#name.to_owned(), #ty) ) }); - Ok(quote! { ::serde_dhall::value::Value::make_record_type( + Ok(quote! { ::serde_dhall::Type::make_record_type( vec![ #(#entries),* ].into_iter() ) }) } @@ -89,7 +89,7 @@ fn derive_for_enum( }) .collect::>()?; - Ok(quote! { ::serde_dhall::value::Value::make_union_type( + Ok(quote! { ::serde_dhall::Type::make_union_type( vec![ #(#entries),* ].into_iter() ) }) } @@ -165,7 +165,7 @@ pub fn derive_static_type_inner( for #ident #ty_generics #where_clause { fn static_type() -> - ::serde_dhall::value::Value { + ::serde_dhall::Type { #(#assertions)* #get_type } diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs index 55e098c..5f386e3 100644 --- a/serde_dhall/src/lib.rs +++ b/serde_dhall/src/lib.rs @@ -106,17 +106,17 @@ //! There are two ways to typecheck a Dhall value: you can provide the type as Dhall text or you //! can let Rust infer it for you. //! -//! To provide a type written in Dhall, first parse it into a [`serde_dhall::Value`][Value], then +//! To provide a type written in Dhall, first parse it into a [`serde_dhall::Type`][Type], then //! pass it to [`from_str_check_type`][from_str_check_type]. //! //! ```rust //! # fn main() -> serde_dhall::de::Result<()> { -//! use serde_dhall::Value; +//! use serde_dhall::Type; //! use std::collections::HashMap; //! //! // Parse a Dhall type //! let point_type_str = "{ x: Natural, y: Natural }"; -//! let point_type: Value = serde_dhall::from_str(point_type_str)?; +//! let point_type: Type = serde_dhall::from_str(point_type_str)?; //! //! // Some Dhall data //! let point_data = "{ x = 1, y = 1 + 1 }"; @@ -176,30 +176,29 @@ pub use de::{from_str, from_str_auto_type, from_str_check_type}; pub use dhall_proc_macros::StaticType; pub use static_type::StaticType; #[doc(inline)] +pub use ty::Type; +#[doc(inline)] pub use value::Value; // A Dhall value. #[doc(hidden)] pub mod value { - use dhall::syntax::Builtin; use dhall::{Normalized, NormalizedExpr, Parsed, SimpleValue}; use super::de::Error; + use super::Type; /// A Dhall value #[derive(Debug, Clone, PartialEq, Eq)] - pub struct Value(Normalized); + pub struct Value(pub(crate) Normalized); impl Value { - pub fn from_str( - s: &str, - ty: Option<&Value>, - ) -> super::de::Result { + pub fn from_str(s: &str, ty: Option<&Type>) -> super::de::Result { Value::from_str_using_dhall_error_type(s, ty).map_err(Error::Dhall) } fn from_str_using_dhall_error_type( s: &str, - ty: Option<&Value>, + ty: Option<&Type>, ) -> dhall::error::Result { let resolved = Parsed::parse_str(s)?.resolve()?; let typed = match ty { @@ -213,41 +212,79 @@ pub mod value { ) -> Result { self.0.to_simple_value() } + } + + impl super::de::sealed::Sealed for Value {} + + impl super::de::Deserialize for Value { + fn from_dhall(v: &Value) -> super::de::Result { + Ok(v.clone()) + } + } +} + +// A Dhall type. +#[doc(hidden)] +pub mod ty { + use dhall::syntax::Builtin; + use dhall::{Normalized, Parsed}; + + use super::de::Error; + + /// A Dhall value + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct Type(Normalized); + + impl Type { + pub fn from_str(s: &str, ty: Option<&Type>) -> super::de::Result { + 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 { + 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 make_builtin_type(b: Builtin) -> Self { - Value(Normalized::make_builtin_type(b)) + Type(Normalized::make_builtin_type(b)) } - pub(crate) fn make_optional_type(t: Value) -> Self { - Value(Normalized::make_optional_type(t.0)) + pub(crate) fn make_optional_type(t: Type) -> Self { + Type(Normalized::make_optional_type(t.0)) } - pub(crate) fn make_list_type(t: Value) -> Self { - Value(Normalized::make_list_type(t.0)) + pub(crate) fn make_list_type(t: Type) -> Self { + Type(Normalized::make_list_type(t.0)) } // Made public for the StaticType derive macro #[doc(hidden)] pub fn make_record_type( - kts: impl Iterator, + kts: impl Iterator, ) -> Self { - Value(Normalized::make_record_type(kts.map(|(k, t)| (k, t.0)))) + Type(Normalized::make_record_type(kts.map(|(k, t)| (k, t.0)))) } #[doc(hidden)] pub fn make_union_type( - kts: impl Iterator)>, + kts: impl Iterator)>, ) -> Self { - Value(Normalized::make_union_type( + Type(Normalized::make_union_type( kts.map(|(k, t)| (k, t.map(|t| t.0))), )) } } - impl super::de::sealed::Sealed for Value {} + impl super::de::sealed::Sealed for Type {} - impl super::de::Deserialize for Value { - fn from_dhall(v: &Value) -> super::de::Result { - Ok(v.clone()) + impl super::de::Deserialize for Type { + fn from_dhall(v: &super::Value) -> super::de::Result { + Ok(Type(v.0.clone())) } } } @@ -255,6 +292,7 @@ pub mod value { /// Deserialize Dhall data to a Rust data structure. pub mod de { use super::StaticType; + use super::Type; use super::Value; pub use error::{Error, Result}; @@ -324,7 +362,7 @@ pub mod de { /// /// Like [from_str], but this additionally checks that /// the type of the provided expression matches the supplied type. - pub fn from_str_check_type(s: &str, ty: &Value) -> Result + pub fn from_str_check_type(s: &str, ty: &Type) -> Result where T: Deserialize, { diff --git a/serde_dhall/src/static_type.rs b/serde_dhall/src/static_type.rs index 1eb9150..921b296 100644 --- a/serde_dhall/src/static_type.rs +++ b/serde_dhall/src/static_type.rs @@ -1,6 +1,6 @@ use dhall::syntax::Builtin; -use crate::Value; +use crate::Type; /// A Rust type that can be represented as a Dhall type. /// @@ -14,14 +14,14 @@ use crate::Value; /// [StaticType] because each different value would /// have a different Dhall record type. pub trait StaticType { - fn static_type() -> Value; + fn static_type() -> Type; } macro_rules! derive_builtin { ($ty:ty, $builtin:ident) => { impl StaticType for $ty { - fn static_type() -> Value { - Value::make_builtin_type(Builtin::$builtin) + fn static_type() -> Type { + Type::make_builtin_type(Builtin::$builtin) } } }; @@ -43,8 +43,8 @@ where A: StaticType, B: StaticType, { - fn static_type() -> Value { - Value::make_record_type( + fn static_type() -> Type { + Type::make_record_type( vec![ ("_1".to_owned(), A::static_type()), ("_2".to_owned(), B::static_type()), @@ -59,8 +59,8 @@ where T: StaticType, E: StaticType, { - fn static_type() -> Value { - Value::make_union_type( + fn static_type() -> Type { + Type::make_union_type( vec![ ("Ok".to_owned(), Some(T::static_type())), ("Err".to_owned(), Some(E::static_type())), @@ -74,8 +74,8 @@ impl StaticType for Option where T: StaticType, { - fn static_type() -> Value { - Value::make_optional_type(T::static_type()) + fn static_type() -> Type { + Type::make_optional_type(T::static_type()) } } @@ -83,8 +83,8 @@ impl StaticType for Vec where T: StaticType, { - fn static_type() -> Value { - Value::make_list_type(T::static_type()) + fn static_type() -> Type { + Type::make_list_type(T::static_type()) } } @@ -92,7 +92,7 @@ impl<'a, T> StaticType for &'a T where T: StaticType, { - fn static_type() -> Value { + fn static_type() -> Type { T::static_type() } } diff --git a/serde_dhall/tests/traits.rs b/serde_dhall/tests/traits.rs index 15a91ed..b2fe6e5 100644 --- a/serde_dhall/tests/traits.rs +++ b/serde_dhall/tests/traits.rs @@ -1,8 +1,8 @@ -use serde_dhall::{from_str, StaticType, Value}; +use serde_dhall::{from_str, StaticType, Type}; #[test] fn test_static_type() { - fn parse(s: &str) -> Value { + fn parse(s: &str) -> Type { from_str(s).unwrap() } diff --git a/test.dhall b/test.dhall new file mode 100644 index 0000000..641c219 --- /dev/null +++ b/test.dhall @@ -0,0 +1,4 @@ +let Prelude = + https://prelude.dhall-lang.org/package.dhall sha256:c1b3fc613aabfb64a9e17f6c0d70fe82016a030beedd79851730993e9083fde2 + +in Prelude -- cgit v1.2.3