summaryrefslogtreecommitdiff
path: root/dhall/src/api
diff options
context:
space:
mode:
authorNadrieril2019-05-09 21:54:45 +0200
committerNadrieril2019-05-09 21:54:45 +0200
commitdae106b3de0888e8a704c0efa3f9d991590f7858 (patch)
tree750daf7cb5b44bed4772ace3457c583c0ef86e4d /dhall/src/api
parent6444faa2dee271e6d22226dc30b659e13fa8aead (diff)
Rewrite the StaticType trait and everything around it
Diffstat (limited to '')
-rw-r--r--dhall/src/api/mod.rs85
-rw-r--r--dhall/src/api/static_type.rs93
-rw-r--r--dhall/src/api/traits/dynamic_type.rs32
-rw-r--r--dhall/src/api/traits/mod.rs4
-rw-r--r--dhall/src/api/traits/static_type.rs149
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>))
- }
-}