diff options
Diffstat (limited to 'dhall/src/api')
-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 |
5 files changed, 174 insertions, 189 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>)) - } -} |