diff options
author | Nadrieril | 2019-05-09 21:54:45 +0200 |
---|---|---|
committer | Nadrieril | 2019-05-09 21:54:45 +0200 |
commit | dae106b3de0888e8a704c0efa3f9d991590f7858 (patch) | |
tree | 750daf7cb5b44bed4772ace3457c583c0ef86e4d /dhall | |
parent | 6444faa2dee271e6d22226dc30b659e13fa8aead (diff) |
Rewrite the StaticType trait and everything around it
Diffstat (limited to '')
-rw-r--r-- | dhall/src/api/mod.rs | 85 | ||||
-rw-r--r-- | dhall/src/api/static_type.rs | 93 | ||||
-rw-r--r-- | dhall/src/api/traits/dynamic_type.rs | 32 | ||||
-rw-r--r-- | dhall/src/api/traits/mod.rs | 4 | ||||
-rw-r--r-- | dhall/src/api/traits/static_type.rs | 149 | ||||
-rw-r--r-- | dhall/src/lib.rs | 10 | ||||
-rw-r--r-- | dhall/src/phase/mod.rs | 57 | ||||
-rw-r--r-- | dhall/src/phase/typecheck.rs | 2 | ||||
-rw-r--r-- | dhall/tests/traits.rs | 67 | ||||
-rw-r--r-- | dhall_proc_macros/src/derive.rs | 66 | ||||
-rw-r--r-- | dhall_proc_macros/src/lib.rs | 6 |
11 files changed, 257 insertions, 314 deletions
diff --git a/dhall/src/api/mod.rs b/dhall/src/api/mod.rs index 0a0ef93..72789d9 100644 --- a/dhall/src/api/mod.rs +++ b/dhall/src/api/mod.rs @@ -1,13 +1,88 @@ mod serde; +pub(crate) mod static_type; pub(crate) mod traits; +// pub struct Value(crate::phase::Normalized); + +pub use typ::Type; + +mod typ { + use crate::core::thunk::{Thunk, TypeThunk}; + use crate::core::value::Value; + use crate::phase::{NormalizedSubExpr, Typed}; + use dhall_syntax::Builtin; + + /// A Dhall expression representing a type. + /// + /// This captures what is usually simply called a "type", like + /// `Bool`, `{ x: Integer }` or `Natural -> Text`. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct Type(Typed); + + impl Type { + pub(crate) fn from_value(v: Value) -> Self { + Type(Typed::from_value_untyped(v)) + } + pub(crate) fn make_builtin_type(b: Builtin) -> Self { + Self::from_value(Value::from_builtin(b)) + } + pub(crate) fn make_optional_type(t: Type) -> Self { + Self::from_value(Value::AppliedBuiltin( + Builtin::Optional, + vec![t.to_thunk()], + )) + } + pub(crate) fn make_list_type(t: Type) -> Self { + Self::from_value(Value::AppliedBuiltin( + Builtin::List, + vec![t.to_thunk()], + )) + } + #[doc(hidden)] + pub fn from_normalized_expr(e: NormalizedSubExpr) -> Self { + Type(Typed::from_normalized_expr_untyped(e)) + } + #[doc(hidden)] + pub fn make_record_type( + kts: impl Iterator<Item = (String, Type)>, + ) -> Self { + Self::from_value(Value::RecordType( + kts.map(|(k, t)| { + (k.into(), TypeThunk::from_thunk(t.to_thunk())) + }) + .collect(), + )) + } + #[doc(hidden)] + pub fn make_union_type( + kts: impl Iterator<Item = (String, Option<Type>)>, + ) -> Self { + Self::from_value(Value::UnionType( + kts.map(|(k, t)| { + (k.into(), t.map(|t| TypeThunk::from_thunk(t.to_thunk()))) + }) + .collect(), + )) + } + + pub(crate) fn to_thunk(&self) -> Thunk { + self.0.to_thunk() + } + #[allow(dead_code)] + pub(crate) fn to_expr(&self) -> NormalizedSubExpr { + self.0.to_expr() + } + } +} + /// Deserialization of Dhall expressions into Rust pub mod de { + pub use super::static_type::StaticType; + pub use super::Type; #[doc(hidden)] - pub use crate::phase::SimpleType; - pub use crate::traits::{Deserialize, SimpleStaticType, StaticType}; + pub use crate::traits::Deserialize; #[doc(hidden)] - pub use dhall_proc_macros::SimpleStaticType; + pub use dhall_proc_macros::StaticType; /// Deserialize an instance of type T from a string of Dhall text. /// @@ -35,6 +110,8 @@ pub mod de { pub fn from_str_auto_type<'a, T: Deserialize<'a> + StaticType>( s: &'a str, ) -> crate::error::Result<T> { - from_str(s, Some(&<T as StaticType>::get_static_type())) + // from_str(s, Some(&<T as StaticType>::static_type())) + // TODO + from_str(s, None) } } diff --git a/dhall/src/api/static_type.rs b/dhall/src/api/static_type.rs new file mode 100644 index 0000000..906bcef --- /dev/null +++ b/dhall/src/api/static_type.rs @@ -0,0 +1,93 @@ +use dhall_syntax::{Builtin, Integer, Natural}; + +use crate::api::Type; + +/// A Rust type that can be represented as a Dhall type. +/// +/// A typical example is `Option<bool>`, +/// represented by the dhall expression `Optional Bool`. +/// +/// This trait can and should be automatically derived. +/// +/// The representation needs to be independent of the value. +/// For this reason, something like `HashMap<String, bool>` cannot implement +/// [StaticType] because each different value would +/// have a different Dhall record type. +pub trait StaticType { + fn static_type() -> Type; +} + +macro_rules! derive_builtin { + ($ty:ty, $builtin:ident) => { + impl StaticType for $ty { + fn static_type() -> Type { + Type::make_builtin_type(Builtin::$builtin) + } + } + }; +} + +derive_builtin!(bool, Bool); +derive_builtin!(Natural, Natural); +derive_builtin!(u64, Natural); +derive_builtin!(Integer, Integer); +derive_builtin!(String, Text); + +impl<A, B> StaticType for (A, B) +where + A: StaticType, + B: StaticType, +{ + fn static_type() -> Type { + Type::make_record_type( + vec![ + ("_1".to_owned(), A::static_type()), + ("_2".to_owned(), B::static_type()), + ] + .into_iter(), + ) + } +} + +impl<T, E> StaticType for std::result::Result<T, E> +where + T: StaticType, + E: StaticType, +{ + fn static_type() -> Type { + Type::make_union_type( + vec![ + ("Ok".to_owned(), Some(T::static_type())), + ("Err".to_owned(), Some(E::static_type())), + ] + .into_iter(), + ) + } +} + +impl<T> StaticType for Option<T> +where + T: StaticType, +{ + fn static_type() -> Type { + Type::make_optional_type(T::static_type()) + } +} + +impl<T> StaticType for Vec<T> +where + T: StaticType, +{ + fn static_type() -> Type { + Type::make_list_type(T::static_type()) + } +} + +impl<'a, T> StaticType for &'a T +where + T: StaticType, +{ + fn static_type() -> Type { + T::static_type() + } +} diff --git a/dhall/src/api/traits/dynamic_type.rs b/dhall/src/api/traits/dynamic_type.rs deleted file mode 100644 index 7763a28..0000000 --- a/dhall/src/api/traits/dynamic_type.rs +++ /dev/null @@ -1,32 +0,0 @@ -use crate::error::TypeError; -use crate::phase::{Normalized, Type, Typed}; -use crate::traits::StaticType; -use std::borrow::Cow; - -pub trait DynamicType { - fn get_type<'a>(&'a self) -> Result<Cow<'a, Type>, TypeError>; -} - -impl<T: StaticType> DynamicType for T { - fn get_type<'a>(&'a self) -> Result<Cow<'a, Type>, TypeError> { - Ok(Cow::Owned(T::get_static_type())) - } -} - -impl DynamicType for Type { - fn get_type(&self) -> Result<Cow<'_, Type>, TypeError> { - self.get_type() - } -} - -impl DynamicType for Normalized { - fn get_type(&self) -> Result<Cow<'_, Type>, TypeError> { - self.0.get_type() - } -} - -impl DynamicType for Typed { - fn get_type(&self) -> Result<Cow<'_, Type>, TypeError> { - self.get_type() - } -} diff --git a/dhall/src/api/traits/mod.rs b/dhall/src/api/traits/mod.rs index 315e17a..3fd21e4 100644 --- a/dhall/src/api/traits/mod.rs +++ b/dhall/src/api/traits/mod.rs @@ -1,6 +1,2 @@ mod deserialize; -mod dynamic_type; -mod static_type; pub use deserialize::Deserialize; -pub use dynamic_type::DynamicType; -pub use static_type::{SimpleStaticType, StaticType}; diff --git a/dhall/src/api/traits/static_type.rs b/dhall/src/api/traits/static_type.rs deleted file mode 100644 index e05dfff..0000000 --- a/dhall/src/api/traits/static_type.rs +++ /dev/null @@ -1,149 +0,0 @@ -use crate::phase::*; -use dhall_proc_macros as dhall; -use dhall_syntax::*; - -/// A value that has a statically-known Dhall type. -/// -/// This trait is strictly more general than [SimpleStaticType]. -/// The reason is that it allows an arbitrary [Type] to be returned -/// instead of just a [SimpleType]. -/// -/// For now the only interesting impl is [SimpleType] itself, who -/// has a statically-known type which is not itself a [SimpleType]. -pub trait StaticType { - fn get_static_type() -> Type; -} - -/// A Rust type that can be represented as a Dhall type. -/// -/// A typical example is `Option<bool>`, -/// represented by the dhall expression `Optional Bool`. -/// -/// This trait can and should be automatically derived. -/// -/// The representation needs to be independent of the value. -/// For this reason, something like `HashMap<String, bool>` cannot implement -/// [SimpleStaticType] because each different value would -/// have a different Dhall record type. -/// -/// The `Simple` in `SimpleStaticType` indicates that the returned type is -/// a [SimpleType]. -pub trait SimpleStaticType { - fn get_simple_static_type() -> SimpleType; -} - -fn mktype(x: SubExpr<X, X>) -> SimpleType { - x.into() -} - -impl<T: SimpleStaticType> StaticType for T { - fn get_static_type() -> Type { - crate::phase::Normalized::from_thunk_and_type( - crate::core::thunk::Thunk::from_normalized_expr( - T::get_simple_static_type().into(), - ), - Type::const_type(), - ) - .to_type() - } -} - -impl StaticType for SimpleType { - /// By definition, a [SimpleType] has type `Type`. - /// This returns the Dhall expression `Type` - fn get_static_type() -> Type { - Type::const_type() - } -} - -impl SimpleStaticType for bool { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!(Bool)) - } -} - -impl SimpleStaticType for Natural { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!(Natural)) - } -} - -impl SimpleStaticType for u32 { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!(Natural)) - } -} - -impl SimpleStaticType for u64 { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!(Natural)) - } -} - -impl SimpleStaticType for Integer { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!(Integer)) - } -} - -impl SimpleStaticType for i32 { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!(Integer)) - } -} - -impl SimpleStaticType for i64 { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!(Integer)) - } -} - -impl SimpleStaticType for String { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!(Text)) - } -} - -impl<A: SimpleStaticType, B: SimpleStaticType> SimpleStaticType for (A, B) { - fn get_simple_static_type() -> SimpleType { - let ta: SubExpr<_, _> = A::get_simple_static_type().into(); - let tb: SubExpr<_, _> = B::get_simple_static_type().into(); - mktype(dhall::subexpr!({ _1: ta, _2: tb })) - } -} - -impl<T: SimpleStaticType> SimpleStaticType for Option<T> { - fn get_simple_static_type() -> SimpleType { - let t: SubExpr<_, _> = T::get_simple_static_type().into(); - mktype(dhall::subexpr!(Optional t)) - } -} - -impl<T: SimpleStaticType> SimpleStaticType for Vec<T> { - fn get_simple_static_type() -> SimpleType { - let t: SubExpr<_, _> = T::get_simple_static_type().into(); - mktype(dhall::subexpr!(List t)) - } -} - -impl<'a, T: SimpleStaticType> SimpleStaticType for &'a T { - fn get_simple_static_type() -> SimpleType { - T::get_simple_static_type() - } -} - -impl<T> SimpleStaticType for std::marker::PhantomData<T> { - fn get_simple_static_type() -> SimpleType { - mktype(dhall::subexpr!({})) - } -} - -impl<T: SimpleStaticType, E: SimpleStaticType> SimpleStaticType - for std::result::Result<T, E> -{ - fn get_simple_static_type() -> SimpleType { - let tt: SubExpr<_, _> = T::get_simple_static_type().into(); - let te: SubExpr<_, _> = E::get_simple_static_type().into(); - mktype(dhall::subexpr!(< Ok: tt | Err: te>)) - } -} diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index b35b2ae..c25fc82 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -35,15 +35,15 @@ //! ### Custom datatype //! //! If you have a custom datatype for which you derived [serde::Deserialize], chances are -//! you will be able to derive [SimpleStaticType][de::SimpleStaticType] for it as well. +//! you will be able to derive [StaticType][de::StaticType] for it as well. //! This gives you access to a dhall representation of your datatype that can be outputted //! to users, and allows easy type-safe deserializing. //! //! ```edition2018 //! use serde::Deserialize; -//! use dhall::de::SimpleStaticType; +//! use dhall::de::StaticType; //! -//! #[derive(Debug, Deserialize, SimpleStaticType)] +//! #[derive(Debug, Deserialize, StaticType)] //! struct Point { //! x: u64, //! y: u64, @@ -68,7 +68,7 @@ //! If you used to consume JSON or YAML in a loosely typed way, you can continue to do so //! with dhall. You only need to replace [serde_json::from_str] or [serde_yaml::from_str] //! with [dhall::de::from_str][de::from_str]. -//! More generally, if the [SimpleStaticType][de::SimpleStaticType] derive doesn't suit your +//! More generally, if the [StaticType][de::StaticType] derive doesn't suit your //! needs, you can still deserialize any valid dhall file that serde can handle. //! //! [serde_json::from_str]: https://docs.serde.rs/serde_json/de/fn.from_str.html @@ -130,4 +130,4 @@ pub mod error; pub(crate) mod phase; pub(crate) use api::traits; -pub use api::de; +pub use api::*; diff --git a/dhall/src/phase/mod.rs b/dhall/src/phase/mod.rs index af39eb6..5262a27 100644 --- a/dhall/src/phase/mod.rs +++ b/dhall/src/phase/mod.rs @@ -49,19 +49,6 @@ pub(crate) enum Typed { #[derive(Debug, Clone)] pub(crate) struct Normalized(pub(crate) Typed); -/// A Dhall expression representing a simple type. -/// -/// This captures what is usually simply called a "type", like -/// `Bool`, `{ x: Integer }` or `Natural -> Text`. -/// -/// For a more general notion of "type", see [Type]. -#[derive(Debug, Clone)] -pub struct SimpleType(pub(crate) NormalizedSubExpr); - -/// A Dhall expression representing a (possibly higher-kinded) type. -/// -/// This includes [SimpleType]s but also higher-kinded expressions like -/// `Type`, `Kind` and `{ x: Type }`. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Type(pub(crate) Typed); @@ -131,6 +118,12 @@ impl Typed { pub(crate) fn from_const(c: Const) -> Self { Typed::Const(c) } + pub(crate) fn from_value_untyped(v: Value) -> Self { + Typed::Untyped(Thunk::from_value(v)) + } + pub(crate) fn from_normalized_expr_untyped(e: NormalizedSubExpr) -> Self { + Typed::from_thunk_untyped(Thunk::from_normalized_expr(e)) + } // TODO: Avoid cloning if possible pub(crate) fn to_value(&self) -> Value { @@ -179,6 +172,7 @@ impl Typed { } impl Type { + // Deprecated pub(crate) fn to_normalized(&self) -> Normalized { self.0.clone().normalize() } @@ -202,19 +196,12 @@ impl Type { self.0.get_type() } - pub(crate) fn const_type() -> Self { - Type::from_const(Const::Type) - } pub(crate) fn from_const(c: Const) -> Self { Type(Typed::from_const(c)) } } impl Normalized { - pub(crate) fn from_thunk_and_type(th: Thunk, t: Type) -> Self { - Normalized(Typed::from_thunk_and_type(th, t)) - } - pub(crate) fn to_expr(&self) -> NormalizedSubExpr { self.0.to_expr() } @@ -225,9 +212,12 @@ impl Normalized { pub(crate) fn to_value(&self) -> Value { self.0.to_value() } - pub(crate) fn to_type(self) -> Type { + pub(crate) fn to_type(&self) -> Type { self.0.to_type() } + pub(crate) fn into_typed(self) -> Typed { + self.0 + } pub(crate) fn get_type(&self) -> Result<Cow<'_, Type>, TypeError> { self.0.get_type() } @@ -301,7 +291,6 @@ macro_rules! derive_traits_for_wrapper_struct { derive_traits_for_wrapper_struct!(Parsed); derive_traits_for_wrapper_struct!(Resolved); derive_traits_for_wrapper_struct!(Normalized); -derive_traits_for_wrapper_struct!(SimpleType); impl Eq for Typed {} impl PartialEq for Typed { @@ -321,27 +310,3 @@ impl Display for Type { self.to_normalized().fmt(f) } } - -// Exposed for the macros -#[doc(hidden)] -impl From<SimpleType> for NormalizedSubExpr { - fn from(x: SimpleType) -> NormalizedSubExpr { - x.0 - } -} - -// Exposed for the macros -#[doc(hidden)] -impl From<NormalizedSubExpr> for SimpleType { - fn from(x: NormalizedSubExpr) -> SimpleType { - SimpleType(x) - } -} - -// Exposed for the macros -#[doc(hidden)] -impl From<Normalized> for Typed { - fn from(x: Normalized) -> Typed { - x.0 - } -} diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs index e1dffb0..7f988c8 100644 --- a/dhall/src/phase/typecheck.rs +++ b/dhall/src/phase/typecheck.rs @@ -391,7 +391,7 @@ fn type_with( let e = e.rewrap(Annot(x, t)); return type_with(ctx, e); } - Embed(p) => p.clone().into(), + Embed(p) => p.clone().into_typed(), Var(var) => match ctx.lookup(&var) { Some(typed) => typed, None => { diff --git a/dhall/tests/traits.rs b/dhall/tests/traits.rs index 65220dc..75eaf75 100644 --- a/dhall/tests/traits.rs +++ b/dhall/tests/traits.rs @@ -1,79 +1,76 @@ #![feature(proc_macro_hygiene)] -use dhall::de::SimpleStaticType; -use dhall_proc_macros; +use dhall::de::{StaticType, Type}; +use dhall_proc_macros::subexpr; use dhall_syntax::{SubExpr, X}; #[test] fn test_static_type() { - fn mktype(x: SubExpr<X, X>) -> dhall::de::SimpleType { - x.into() + fn mktype(x: SubExpr<X, X>) -> Type { + Type::from_normalized_expr(x) } + assert_eq!(bool::static_type(), mktype(subexpr!(Bool))); + assert_eq!(String::static_type(), mktype(subexpr!(Text))); assert_eq!( - bool::get_simple_static_type(), - mktype(dhall_proc_macros::subexpr!(Bool)) + <Option<bool>>::static_type(), + mktype(subexpr!(Optional Bool)) ); assert_eq!( - String::get_simple_static_type(), - mktype(dhall_proc_macros::subexpr!(Text)) - ); - assert_eq!( - <Option<bool>>::get_simple_static_type(), - mktype(dhall_proc_macros::subexpr!(Optional Bool)) - ); - assert_eq!( - <(bool, Option<String>)>::get_simple_static_type(), - mktype(dhall_proc_macros::subexpr!({ _1: Bool, _2: Optional Text })) + <(bool, Vec<String>)>::static_type(), + mktype(subexpr!({ _1: Bool, _2: List Text })) ); - #[derive(dhall::de::SimpleStaticType)] + #[derive(dhall::de::StaticType)] #[allow(dead_code)] struct A { field1: bool, field2: Option<bool>, } assert_eq!( - <A as dhall::de::SimpleStaticType>::get_simple_static_type(), - mktype( - dhall_proc_macros::subexpr!({ field1: Bool, field2: Optional Bool }) - ) + <A as dhall::de::StaticType>::static_type(), + mktype(subexpr!({ field1: Bool, field2: Optional Bool })) ); - #[derive(SimpleStaticType)] + #[derive(StaticType)] #[allow(dead_code)] struct B<'a, T: 'a> { field1: &'a T, field2: Option<T>, } - assert_eq!( - <B<'static, bool>>::get_simple_static_type(), - A::get_simple_static_type() - ); + assert_eq!(<B<'static, bool>>::static_type(), A::static_type()); - #[derive(SimpleStaticType)] + #[derive(StaticType)] #[allow(dead_code)] struct C<T>(T, Option<String>); assert_eq!( - <C<bool>>::get_simple_static_type(), - <(bool, Option<String>)>::get_simple_static_type() + <C<bool>>::static_type(), + <(bool, Option<String>)>::static_type() ); - #[derive(SimpleStaticType)] + #[derive(StaticType)] #[allow(dead_code)] struct D(); assert_eq!( - <C<D>>::get_simple_static_type(), - mktype(dhall_proc_macros::subexpr!({ _1: {}, _2: Optional Text })) + <C<D>>::static_type(), + mktype(subexpr!({ _1: {}, _2: Optional Text })) ); - #[derive(SimpleStaticType)] + #[derive(StaticType)] #[allow(dead_code)] enum E<T> { A(T), B(String), }; assert_eq!( - <E<bool>>::get_simple_static_type(), - mktype(dhall_proc_macros::subexpr!(< A: Bool | B: Text >)) + <E<bool>>::static_type(), + mktype(subexpr!(< A: Bool | B: Text >)) ); + + #[derive(StaticType)] + #[allow(dead_code)] + enum F { + A, + B(bool), + }; + assert_eq!(F::static_type(), mktype(subexpr!(< A | B: Bool >))); } diff --git a/dhall_proc_macros/src/derive.rs b/dhall_proc_macros/src/derive.rs index a5f0925..725cdfb 100644 --- a/dhall_proc_macros/src/derive.rs +++ b/dhall_proc_macros/src/derive.rs @@ -6,19 +6,19 @@ use syn::spanned::Spanned; use syn::Error; use syn::{parse_quote, DeriveInput}; -pub fn derive_simple_static_type(input: TokenStream) -> TokenStream { - TokenStream::from(match derive_simple_static_type_inner(input) { +pub fn derive_static_type(input: TokenStream) -> TokenStream { + TokenStream::from(match derive_static_type_inner(input) { Ok(tokens) => tokens, Err(err) => err.to_compile_error(), }) } -fn get_simple_static_type<T>(ty: T) -> proc_macro2::TokenStream +fn static_type<T>(ty: T) -> proc_macro2::TokenStream where T: quote::ToTokens, { quote!( - <#ty as ::dhall::de::SimpleStaticType>::get_simple_static_type() + <#ty as ::dhall::de::StaticType>::static_type() ) } @@ -48,39 +48,35 @@ fn derive_for_struct( .collect(), syn::Fields::Unit => vec![], }; - let fields = fields - .into_iter() - .map(|(name, ty)| { - let name = dhall_syntax::Label::from(name); - constraints.push(ty.clone()); - let ty = get_simple_static_type(ty); - (name, quote!(#ty.into())) - }) - .collect(); - let record = - crate::quote::quote_exprf(dhall_syntax::ExprF::RecordType(fields)); - Ok(quote! { dhall_syntax::rc(#record) }) + let entries = fields.into_iter().map(|(name, ty)| { + constraints.push(ty.clone()); + let ty = static_type(ty); + quote!( (#name.to_owned(), #ty) ) + }); + Ok(quote! { ::dhall::de::Type::make_record_type( + vec![ #(#entries),* ].into_iter() + ) }) } fn derive_for_enum( data: &syn::DataEnum, constraints: &mut Vec<syn::Type>, ) -> Result<proc_macro2::TokenStream, Error> { - let variants = data + let entries: Vec<_> = data .variants .iter() .map(|v| { - let name = dhall_syntax::Label::from(v.ident.to_string()); + let name = v.ident.to_string(); match &v.fields { - syn::Fields::Unit => Ok((name, None)), + syn::Fields::Unit => Ok(quote!( (#name.to_owned(), None) )), syn::Fields::Unnamed(fields) if fields.unnamed.is_empty() => { - Ok((name, None)) + Ok(quote!( (#name.to_owned(), None) )) } syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { let ty = &fields.unnamed.iter().next().unwrap().ty; constraints.push(ty.clone()); - let ty = get_simple_static_type(ty); - Ok((name, Some(quote!(#ty.into())))) + let ty = static_type(ty); + Ok(quote!( (#name.to_owned(), Some(#ty)) )) } syn::Fields::Unnamed(_) => Err(Error::new( v.span(), @@ -94,17 +90,17 @@ fn derive_for_enum( }) .collect::<Result<_, Error>>()?; - let union = - crate::quote::quote_exprf(dhall_syntax::ExprF::UnionType(variants)); - Ok(quote! { dhall_syntax::rc(#union) }) + Ok(quote! { ::dhall::de::Type::make_union_type( + vec![ #(#entries),* ].into_iter() + ) }) } -pub fn derive_simple_static_type_inner( +pub fn derive_static_type_inner( input: TokenStream, ) -> Result<proc_macro2::TokenStream, Error> { let input: DeriveInput = syn::parse_macro_input::parse(input)?; - // List of types that must impl Type + // List of types that must impl StaticType let mut constraints = vec![]; let get_type = match &input.data { @@ -132,13 +128,13 @@ pub fn derive_simple_static_type_inner( // Hygienic errors let assertions = constraints.iter().enumerate().map(|(i, ty)| { - // Ensure that ty: Type, with an appropriate span + // Ensure that ty: StaticType, with an appropriate span let assert_name = syn::Ident::new(&format!("_AssertType{}", i), ty.span()); let mut local_where_clause = orig_where_clause.clone(); local_where_clause .predicates - .push(parse_quote!(#ty: ::dhall::de::SimpleStaticType)); + .push(parse_quote!(#ty: ::dhall::de::StaticType)); let phantoms = generics.params.iter().map(|param| match param { syn::GenericParam::Type(syn::TypeParam { ident, .. }) => { quote!(#ident) @@ -155,23 +151,23 @@ pub fn derive_simple_static_type_inner( } }); - // Ensure that all the fields have a Type impl + // Ensure that all the fields have a StaticType impl let mut where_clause = orig_where_clause.clone(); for ty in constraints.iter() { where_clause .predicates - .push(parse_quote!(#ty: ::dhall::de::SimpleStaticType)); + .push(parse_quote!(#ty: ::dhall::de::StaticType)); } let ident = &input.ident; let tokens = quote! { - impl #impl_generics ::dhall::de::SimpleStaticType + impl #impl_generics ::dhall::de::StaticType for #ident #ty_generics #where_clause { - fn get_simple_static_type() -> - ::dhall::de::SimpleType { + fn static_type() -> + ::dhall::de::Type { #(#assertions)* - ::dhall::de::SimpleType::from(#get_type) + #get_type } } }; diff --git a/dhall_proc_macros/src/lib.rs b/dhall_proc_macros/src/lib.rs index 1124968..e4aa8b5 100644 --- a/dhall_proc_macros/src/lib.rs +++ b/dhall_proc_macros/src/lib.rs @@ -20,7 +20,7 @@ pub fn subexpr(input: TokenStream) -> TokenStream { quote::subexpr(input) } -#[proc_macro_derive(SimpleStaticType)] -pub fn derive_simple_static_type(input: TokenStream) -> TokenStream { - derive::derive_simple_static_type(input) +#[proc_macro_derive(StaticType)] +pub fn derive_static_type(input: TokenStream) -> TokenStream { + derive::derive_static_type(input) } |