From 5b91eaa9d6b70a2ac72fe19f2d21871c8d94b017 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 6 May 2019 23:21:19 +0200 Subject: Move api-related modules into an api module --- dhall/src/api/traits/deserialize.rs | 53 +++++++++++++ dhall/src/api/traits/dynamic_type.rs | 32 ++++++++ dhall/src/api/traits/mod.rs | 6 ++ dhall/src/api/traits/static_type.rs | 149 +++++++++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 dhall/src/api/traits/deserialize.rs create mode 100644 dhall/src/api/traits/dynamic_type.rs create mode 100644 dhall/src/api/traits/mod.rs create mode 100644 dhall/src/api/traits/static_type.rs (limited to 'dhall/src/api/traits') diff --git a/dhall/src/api/traits/deserialize.rs b/dhall/src/api/traits/deserialize.rs new file mode 100644 index 0000000..9673cf9 --- /dev/null +++ b/dhall/src/api/traits/deserialize.rs @@ -0,0 +1,53 @@ +use crate::error::*; +use crate::phase::*; + +/// A data structure that can be deserialized from a Dhall expression +/// +/// This is automatically implemented for any type that [serde][serde] +/// can deserialize. +/// +/// This trait cannot be implemented manually. +pub trait Deserialize<'de>: Sized { + /// See [dhall::de::from_str][crate::de::from_str] + fn from_str(s: &'de str, ty: Option<&Type>) -> Result; +} + +impl<'de> Deserialize<'de> for Parsed { + /// Simply parses the provided string. Ignores the + /// provided type. + fn from_str(s: &'de str, _: Option<&Type>) -> Result { + Ok(Parsed::parse_str(s)?) + } +} + +impl<'de> Deserialize<'de> for Resolved { + /// Parses and resolves the provided string. Ignores the + /// provided type. + fn from_str(s: &'de str, ty: Option<&Type>) -> Result { + Ok(Parsed::from_str(s, ty)?.resolve()?) + } +} + +impl<'de> Deserialize<'de> for Typed { + /// Parses, resolves and typechecks the provided string. + fn from_str(s: &'de str, ty: Option<&Type>) -> Result { + let resolved = Resolved::from_str(s, ty)?; + match ty { + None => Ok(resolved.typecheck()?), + Some(t) => Ok(resolved.typecheck_with(t)?), + } + } +} + +impl<'de> Deserialize<'de> for Normalized { + /// Parses, resolves, typechecks and normalizes the provided string. + fn from_str(s: &'de str, ty: Option<&Type>) -> Result { + Ok(Typed::from_str(s, ty)?.normalize()) + } +} + +impl<'de> Deserialize<'de> for Type { + fn from_str(s: &'de str, ty: Option<&Type>) -> Result { + Ok(Normalized::from_str(s, ty)?.to_type()) + } +} diff --git a/dhall/src/api/traits/dynamic_type.rs b/dhall/src/api/traits/dynamic_type.rs new file mode 100644 index 0000000..7763a28 --- /dev/null +++ b/dhall/src/api/traits/dynamic_type.rs @@ -0,0 +1,32 @@ +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, TypeError>; +} + +impl DynamicType for T { + fn get_type<'a>(&'a self) -> Result, TypeError> { + Ok(Cow::Owned(T::get_static_type())) + } +} + +impl DynamicType for Type { + fn get_type(&self) -> Result, TypeError> { + self.get_type() + } +} + +impl DynamicType for Normalized { + fn get_type(&self) -> Result, TypeError> { + self.0.get_type() + } +} + +impl DynamicType for Typed { + fn get_type(&self) -> Result, TypeError> { + self.get_type() + } +} diff --git a/dhall/src/api/traits/mod.rs b/dhall/src/api/traits/mod.rs new file mode 100644 index 0000000..315e17a --- /dev/null +++ b/dhall/src/api/traits/mod.rs @@ -0,0 +1,6 @@ +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 new file mode 100644 index 0000000..8b141a0 --- /dev/null +++ b/dhall/src/api/traits/static_type.rs @@ -0,0 +1,149 @@ +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`, +/// 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` 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) -> SimpleType { + x.into() +} + +impl StaticType for T { + fn get_static_type() -> Type { + crate::phase::Normalized::from_thunk_and_type( + crate::phase::normalize::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 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 SimpleStaticType for Option { + fn get_simple_static_type() -> SimpleType { + let t: SubExpr<_, _> = T::get_simple_static_type().into(); + mktype(dhall::subexpr!(Optional t)) + } +} + +impl SimpleStaticType for Vec { + 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 SimpleStaticType for std::marker::PhantomData { + fn get_simple_static_type() -> SimpleType { + mktype(dhall::subexpr!({})) + } +} + +impl SimpleStaticType + for std::result::Result +{ + 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>)) + } +} -- cgit v1.2.3 From 55b5be3407a8528bc47482a591b168a7cb0ce91e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 6 May 2019 23:52:15 +0200 Subject: Move main datatypes into their own modules --- dhall/src/api/traits/static_type.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'dhall/src/api/traits') diff --git a/dhall/src/api/traits/static_type.rs b/dhall/src/api/traits/static_type.rs index 8b141a0..e05dfff 100644 --- a/dhall/src/api/traits/static_type.rs +++ b/dhall/src/api/traits/static_type.rs @@ -39,7 +39,7 @@ fn mktype(x: SubExpr) -> SimpleType { impl StaticType for T { fn get_static_type() -> Type { crate::phase::Normalized::from_thunk_and_type( - crate::phase::normalize::Thunk::from_normalized_expr( + crate::core::thunk::Thunk::from_normalized_expr( T::get_simple_static_type().into(), ), Type::const_type(), -- cgit v1.2.3