summaryrefslogtreecommitdiff
path: root/serde_dhall
diff options
context:
space:
mode:
authorNadrieril2020-03-22 22:27:56 +0000
committerNadrieril2020-03-31 21:45:32 +0100
commit3a5f2044954aae7278f16e30561a81626dba6923 (patch)
tree1ee01a698c85540d8816dabeb121d3d2085833c7 /serde_dhall
parent263fbebda7bc3c0f8c4497e1e508125ca91382f1 (diff)
Move mod simple into value
Diffstat (limited to 'serde_dhall')
-rw-r--r--serde_dhall/src/deserialize.rs2
-rw-r--r--serde_dhall/src/lib.rs5
-rw-r--r--serde_dhall/src/options.rs2
-rw-r--r--serde_dhall/src/simple.rs224
-rw-r--r--serde_dhall/src/value.rs252
5 files changed, 240 insertions, 245 deletions
diff --git a/serde_dhall/src/deserialize.rs b/serde_dhall/src/deserialize.rs
index 43b7914..ab5580e 100644
--- a/serde_dhall/src/deserialize.rs
+++ b/serde_dhall/src/deserialize.rs
@@ -5,7 +5,7 @@ use std::borrow::Cow;
use dhall::syntax::NumKind;
-use crate::simple::SimpleValue;
+use crate::value::SimpleValue;
use crate::{Error, Result, Value};
pub trait Sealed {}
diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs
index c6c6bf9..02b34a7 100644
--- a/serde_dhall/src/lib.rs
+++ b/serde_dhall/src/lib.rs
@@ -179,8 +179,6 @@ mod deserialize;
mod error;
/// Common patterns made easier
mod shortcuts;
-/// Serde-compatible Dhall types
-mod simple;
mod static_type;
/// Dhall values
mod value;
@@ -192,6 +190,5 @@ pub use deserialize::Deserialize;
pub(crate) use deserialize::Sealed;
pub use error::{Error, Result};
pub use shortcuts::{from_str, from_str_manual_type, from_str_static_type};
-pub use simple::SimpleType;
pub use static_type::StaticType;
-pub use value::Value;
+pub use value::{SimpleType, Value};
diff --git a/serde_dhall/src/options.rs b/serde_dhall/src/options.rs
index 0072393..f468cf0 100644
--- a/serde_dhall/src/options.rs
+++ b/serde_dhall/src/options.rs
@@ -121,7 +121,7 @@ impl<'a, T> Options<'a, T> {
};
let typed = match &self.annot {
None => resolved.typecheck()?,
- Some(ty) => resolved.typecheck_with(&ty.to_value().hir)?,
+ Some(ty) => resolved.typecheck_with(ty.to_value().as_hir())?,
};
Ok(Value::from_nir(typed.normalize().as_nir()))
}
diff --git a/serde_dhall/src/simple.rs b/serde_dhall/src/simple.rs
deleted file mode 100644
index c1f0047..0000000
--- a/serde_dhall/src/simple.rs
+++ /dev/null
@@ -1,224 +0,0 @@
-use std::collections::{BTreeMap, HashMap};
-
-use dhall::semantics::{Hir, HirKind, Nir, NirKind};
-use dhall::syntax::{Builtin, ExprKind, NumKind, Span};
-
-use crate::{Deserialize, Error, Result, Sealed, Value};
-
-/// A simple value of the kind that can be decoded with serde
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub(crate) enum SimpleValue {
- Num(NumKind),
- Text(String),
- Optional(Option<Box<SimpleValue>>),
- List(Vec<SimpleValue>),
- Record(BTreeMap<String, SimpleValue>),
- Union(String, Option<Box<SimpleValue>>),
-}
-
-/// The type of a value that can be decoded by Serde, like `{ x: Bool, y: List Natural }`.
-///
-/// A `SimpleType` is used when deserializing values to ensure they are of the expected type.
-/// Rather than letting `serde` handle potential type mismatches, this uses the type-checking
-/// capabilities of Dhall to catch errors early and cleanly indicate in the user's code where the
-/// mismatch happened.
-///
-/// You would typically not manipulate `SimpleType`s by hand but rather let Rust infer it for your
-/// datatype using the [`StaticType`][TODO] trait, and methods that require it like
-/// [`from_file_static_type`][TODO] and [`Options::static_type_annotation`][TODO]. If you need to supply a
-/// `SimpleType` manually however, you can deserialize it like any other Dhall value using the
-/// functions provided by this crate.
-///
-/// # Examples
-///
-/// ```rust
-/// # fn main() -> serde_dhall::Result<()> {
-/// use std::collections::HashMap;
-/// use serde_dhall::SimpleType;
-///
-/// let ty: SimpleType =
-/// serde_dhall::from_str("{ x: Natural, y: Natural }")?;
-///
-/// let mut map = HashMap::new();
-/// map.insert("x".to_string(), SimpleType::Natural);
-/// map.insert("y".to_string(), SimpleType::Natural);
-/// assert_eq!(ty, SimpleType::Record(map));
-/// # Ok(())
-/// # }
-/// ```
-///
-/// ```rust
-/// # fn main() -> serde_dhall::Result<()> {
-/// use serde_dhall::{SimpleType, StaticType};
-///
-/// #[derive(StaticType)]
-/// struct Foo {
-/// x: bool,
-/// y: Vec<u64>,
-/// }
-///
-/// let ty: SimpleType =
-/// serde_dhall::from_str("{ x: Bool, y: List Natural }")?;
-///
-/// assert_eq!(ty, Foo::static_type());
-/// # Ok(())
-/// # }
-/// ```
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum SimpleType {
- /// Corresponds to the Dhall type `Bool`
- Bool,
- /// Corresponds to the Dhall type `Natural`
- Natural,
- /// Corresponds to the Dhall type `Integer`
- Integer,
- /// Corresponds to the Dhall type `Double`
- Double,
- /// Corresponds to the Dhall type `Text`
- Text,
- /// Corresponds to the Dhall type `Optional T`
- Optional(Box<SimpleType>),
- /// Corresponds to the Dhall type `List T`
- List(Box<SimpleType>),
- /// Corresponds to the Dhall type `{ x : T, y : U }`
- Record(HashMap<String, SimpleType>),
- /// Corresponds to the Dhall type `< x : T | y : U >`
- Union(HashMap<String, Option<SimpleType>>),
-}
-
-impl SimpleValue {
- pub(crate) fn from_nir(nir: &Nir) -> Option<Self> {
- Some(match nir.kind() {
- NirKind::Num(lit) => SimpleValue::Num(lit.clone()),
- NirKind::TextLit(x) => SimpleValue::Text(
- x.as_text()
- .expect("Normal form should ensure the text is a string"),
- ),
- NirKind::EmptyOptionalLit(_) => SimpleValue::Optional(None),
- NirKind::NEOptionalLit(x) => {
- SimpleValue::Optional(Some(Box::new(Self::from_nir(x)?)))
- }
- NirKind::EmptyListLit(_) => SimpleValue::List(vec![]),
- NirKind::NEListLit(xs) => SimpleValue::List(
- xs.iter().map(Self::from_nir).collect::<Option<_>>()?,
- ),
- NirKind::RecordLit(kvs) => SimpleValue::Record(
- kvs.iter()
- .map(|(k, v)| Some((k.into(), Self::from_nir(v)?)))
- .collect::<Option<_>>()?,
- ),
- NirKind::UnionLit(field, x, _) => SimpleValue::Union(
- field.into(),
- Some(Box::new(Self::from_nir(x)?)),
- ),
- NirKind::UnionConstructor(field, ty)
- if ty.get(field).map(|f| f.is_some()) == Some(false) =>
- {
- SimpleValue::Union(field.into(), None)
- }
- _ => return None,
- })
- }
-}
-
-impl SimpleType {
- pub(crate) fn from_nir(nir: &Nir) -> Option<Self> {
- Some(match nir.kind() {
- NirKind::BuiltinType(b) => match b {
- Builtin::Bool => SimpleType::Bool,
- Builtin::Natural => SimpleType::Natural,
- Builtin::Integer => SimpleType::Integer,
- Builtin::Double => SimpleType::Double,
- Builtin::Text => SimpleType::Text,
- _ => unreachable!(),
- },
- NirKind::OptionalType(t) => {
- SimpleType::Optional(Box::new(Self::from_nir(t)?))
- }
- NirKind::ListType(t) => {
- SimpleType::List(Box::new(Self::from_nir(t)?))
- }
- NirKind::RecordType(kts) => SimpleType::Record(
- kts.iter()
- .map(|(k, v)| Some((k.into(), Self::from_nir(v)?)))
- .collect::<Option<_>>()?,
- ),
- NirKind::UnionType(kts) => SimpleType::Union(
- kts.iter()
- .map(|(k, v)| {
- Some((
- k.into(),
- v.as_ref()
- .map(|v| Ok(Self::from_nir(v)?))
- .transpose()?,
- ))
- })
- .collect::<Option<_>>()?,
- ),
- _ => return None,
- })
- }
-
- pub(crate) fn to_value(&self) -> Value {
- Value {
- hir: self.to_hir(),
- as_simple_val: None,
- as_simple_ty: Some(self.clone()),
- }
- }
- pub(crate) fn to_hir(&self) -> Hir {
- let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial);
- hir(match self {
- SimpleType::Bool => ExprKind::Builtin(Builtin::Bool),
- SimpleType::Natural => ExprKind::Builtin(Builtin::Natural),
- SimpleType::Integer => ExprKind::Builtin(Builtin::Integer),
- SimpleType::Double => ExprKind::Builtin(Builtin::Double),
- SimpleType::Text => ExprKind::Builtin(Builtin::Text),
- SimpleType::Optional(t) => ExprKind::App(
- hir(ExprKind::Builtin(Builtin::Optional)),
- t.to_hir(),
- ),
- SimpleType::List(t) => {
- ExprKind::App(hir(ExprKind::Builtin(Builtin::List)), t.to_hir())
- }
- SimpleType::Record(kts) => ExprKind::RecordType(
- kts.into_iter()
- .map(|(k, t)| (k.as_str().into(), t.to_hir()))
- .collect(),
- ),
- SimpleType::Union(kts) => ExprKind::UnionType(
- kts.into_iter()
- .map(|(k, t)| {
- (k.as_str().into(), t.as_ref().map(|t| t.to_hir()))
- })
- .collect(),
- ),
- })
- }
-}
-
-impl Sealed for SimpleValue {}
-
-impl Deserialize for SimpleValue {
- fn from_dhall(v: &Value) -> Result<Self> {
- v.to_simple_value().ok_or_else(|| {
- Error::Deserialize(format!(
- "this cannot be deserialized into a simple type: {}",
- v
- ))
- })
- }
-}
-
-impl Sealed for SimpleType {}
-
-impl Deserialize for SimpleType {
- fn from_dhall(v: &Value) -> Result<Self> {
- v.to_simple_type().ok_or_else(|| {
- Error::Deserialize(format!(
- "this cannot be deserialized into a simple type: {}",
- v
- ))
- })
- }
-}
diff --git a/serde_dhall/src/value.rs b/serde_dhall/src/value.rs
index 88727bc..f542f0a 100644
--- a/serde_dhall/src/value.rs
+++ b/serde_dhall/src/value.rs
@@ -1,19 +1,101 @@
-use dhall::semantics::{Hir, Nir};
-use dhall::syntax::Expr;
+use std::collections::{BTreeMap, HashMap};
-use crate::simple::{SimpleType, SimpleValue};
-use crate::{Deserialize, Error, Sealed};
+use dhall::semantics::{Hir, HirKind, Nir, NirKind};
+use dhall::syntax::{Builtin, Expr, ExprKind, NumKind, Span};
+
+use crate::{Deserialize, Error, Result, Sealed};
#[doc(hidden)]
/// An arbitrary Dhall value.
#[derive(Debug, Clone)]
pub struct Value {
/// Invariant: in normal form
- pub(crate) hir: Hir,
+ hir: Hir,
/// Cached conversions because they are annoying to construct from Hir.
/// At most one of them will be `Some`.
- pub(crate) as_simple_val: Option<SimpleValue>,
- pub(crate) as_simple_ty: Option<SimpleType>,
+ as_simple_val: Option<SimpleValue>,
+ as_simple_ty: Option<SimpleType>,
+}
+
+/// A simple value of the kind that can be decoded with serde
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub(crate) enum SimpleValue {
+ Num(NumKind),
+ Text(String),
+ Optional(Option<Box<SimpleValue>>),
+ List(Vec<SimpleValue>),
+ Record(BTreeMap<String, SimpleValue>),
+ Union(String, Option<Box<SimpleValue>>),
+}
+
+/// The type of a value that can be decoded by Serde, like `{ x: Bool, y: List Natural }`.
+///
+/// A `SimpleType` is used when deserializing values to ensure they are of the expected type.
+/// Rather than letting `serde` handle potential type mismatches, this uses the type-checking
+/// capabilities of Dhall to catch errors early and cleanly indicate in the user's code where the
+/// mismatch happened.
+///
+/// You would typically not manipulate `SimpleType`s by hand but rather let Rust infer it for your
+/// datatype using the [`StaticType`][TODO] trait, and methods that require it like
+/// [`from_file_static_type`][TODO] and [`Options::static_type_annotation`][TODO]. If you need to supply a
+/// `SimpleType` manually however, you can deserialize it like any other Dhall value using the
+/// functions provided by this crate.
+///
+/// # Examples
+///
+/// ```rust
+/// # fn main() -> serde_dhall::Result<()> {
+/// use std::collections::HashMap;
+/// use serde_dhall::SimpleType;
+///
+/// let ty: SimpleType =
+/// serde_dhall::from_str("{ x: Natural, y: Natural }")?;
+///
+/// let mut map = HashMap::new();
+/// map.insert("x".to_string(), SimpleType::Natural);
+/// map.insert("y".to_string(), SimpleType::Natural);
+/// assert_eq!(ty, SimpleType::Record(map));
+/// # Ok(())
+/// # }
+/// ```
+///
+/// ```rust
+/// # fn main() -> serde_dhall::Result<()> {
+/// use serde_dhall::{SimpleType, StaticType};
+///
+/// #[derive(StaticType)]
+/// struct Foo {
+/// x: bool,
+/// y: Vec<u64>,
+/// }
+///
+/// let ty: SimpleType =
+/// serde_dhall::from_str("{ x: Bool, y: List Natural }")?;
+///
+/// assert_eq!(ty, Foo::static_type());
+/// # Ok(())
+/// # }
+/// ```
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum SimpleType {
+ /// Corresponds to the Dhall type `Bool`
+ Bool,
+ /// Corresponds to the Dhall type `Natural`
+ Natural,
+ /// Corresponds to the Dhall type `Integer`
+ Integer,
+ /// Corresponds to the Dhall type `Double`
+ Double,
+ /// Corresponds to the Dhall type `Text`
+ Text,
+ /// Corresponds to the Dhall type `Optional T`
+ Optional(Box<SimpleType>),
+ /// Corresponds to the Dhall type `List T`
+ List(Box<SimpleType>),
+ /// Corresponds to the Dhall type `{ x : T, y : U }`
+ Record(HashMap<String, SimpleType>),
+ /// Corresponds to the Dhall type `< x : T | y : U >`
+ Union(HashMap<String, Option<SimpleType>>),
}
impl Value {
@@ -25,6 +107,10 @@ impl Value {
}
}
+ pub(crate) fn as_hir(&self) -> &Hir {
+ &self.hir
+ }
+
/// Converts a Value into a SimpleValue.
pub(crate) fn to_simple_value(&self) -> Option<SimpleValue> {
self.as_simple_val.clone()
@@ -41,22 +127,158 @@ impl Value {
}
}
-impl Eq for Value {}
-impl PartialEq for Value {
- fn eq(&self, other: &Self) -> bool {
- self.hir == other.hir
+impl SimpleValue {
+ pub(crate) fn from_nir(nir: &Nir) -> Option<Self> {
+ Some(match nir.kind() {
+ NirKind::Num(lit) => SimpleValue::Num(lit.clone()),
+ NirKind::TextLit(x) => SimpleValue::Text(
+ x.as_text()
+ .expect("Normal form should ensure the text is a string"),
+ ),
+ NirKind::EmptyOptionalLit(_) => SimpleValue::Optional(None),
+ NirKind::NEOptionalLit(x) => {
+ SimpleValue::Optional(Some(Box::new(Self::from_nir(x)?)))
+ }
+ NirKind::EmptyListLit(_) => SimpleValue::List(vec![]),
+ NirKind::NEListLit(xs) => SimpleValue::List(
+ xs.iter().map(Self::from_nir).collect::<Option<_>>()?,
+ ),
+ NirKind::RecordLit(kvs) => SimpleValue::Record(
+ kvs.iter()
+ .map(|(k, v)| Some((k.into(), Self::from_nir(v)?)))
+ .collect::<Option<_>>()?,
+ ),
+ NirKind::UnionLit(field, x, _) => SimpleValue::Union(
+ field.into(),
+ Some(Box::new(Self::from_nir(x)?)),
+ ),
+ NirKind::UnionConstructor(field, ty)
+ if ty.get(field).map(|f| f.is_some()) == Some(false) =>
+ {
+ SimpleValue::Union(field.into(), None)
+ }
+ _ => return None,
+ })
}
}
-impl std::fmt::Display for Value {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
- self.to_expr().fmt(f)
+
+impl SimpleType {
+ pub(crate) fn from_nir(nir: &Nir) -> Option<Self> {
+ Some(match nir.kind() {
+ NirKind::BuiltinType(b) => match b {
+ Builtin::Bool => SimpleType::Bool,
+ Builtin::Natural => SimpleType::Natural,
+ Builtin::Integer => SimpleType::Integer,
+ Builtin::Double => SimpleType::Double,
+ Builtin::Text => SimpleType::Text,
+ _ => unreachable!(),
+ },
+ NirKind::OptionalType(t) => {
+ SimpleType::Optional(Box::new(Self::from_nir(t)?))
+ }
+ NirKind::ListType(t) => {
+ SimpleType::List(Box::new(Self::from_nir(t)?))
+ }
+ NirKind::RecordType(kts) => SimpleType::Record(
+ kts.iter()
+ .map(|(k, v)| Some((k.into(), Self::from_nir(v)?)))
+ .collect::<Option<_>>()?,
+ ),
+ NirKind::UnionType(kts) => SimpleType::Union(
+ kts.iter()
+ .map(|(k, v)| {
+ Some((
+ k.into(),
+ v.as_ref()
+ .map(|v| Ok(Self::from_nir(v)?))
+ .transpose()?,
+ ))
+ })
+ .collect::<Option<_>>()?,
+ ),
+ _ => return None,
+ })
+ }
+
+ pub(crate) fn to_value(&self) -> Value {
+ Value {
+ hir: self.to_hir(),
+ as_simple_val: None,
+ as_simple_ty: Some(self.clone()),
+ }
+ }
+ pub(crate) fn to_hir(&self) -> Hir {
+ let hir = |k| Hir::new(HirKind::Expr(k), Span::Artificial);
+ hir(match self {
+ SimpleType::Bool => ExprKind::Builtin(Builtin::Bool),
+ SimpleType::Natural => ExprKind::Builtin(Builtin::Natural),
+ SimpleType::Integer => ExprKind::Builtin(Builtin::Integer),
+ SimpleType::Double => ExprKind::Builtin(Builtin::Double),
+ SimpleType::Text => ExprKind::Builtin(Builtin::Text),
+ SimpleType::Optional(t) => ExprKind::App(
+ hir(ExprKind::Builtin(Builtin::Optional)),
+ t.to_hir(),
+ ),
+ SimpleType::List(t) => {
+ ExprKind::App(hir(ExprKind::Builtin(Builtin::List)), t.to_hir())
+ }
+ SimpleType::Record(kts) => ExprKind::RecordType(
+ kts.into_iter()
+ .map(|(k, t)| (k.as_str().into(), t.to_hir()))
+ .collect(),
+ ),
+ SimpleType::Union(kts) => ExprKind::UnionType(
+ kts.into_iter()
+ .map(|(k, t)| {
+ (k.as_str().into(), t.as_ref().map(|t| t.to_hir()))
+ })
+ .collect(),
+ ),
+ })
}
}
impl Sealed for Value {}
+impl Sealed for SimpleValue {}
+impl Sealed for SimpleType {}
impl Deserialize for Value {
- fn from_dhall(v: &Value) -> Result<Self, Error> {
+ fn from_dhall(v: &Value) -> Result<Self> {
Ok(v.clone())
}
}
+impl Deserialize for SimpleValue {
+ fn from_dhall(v: &Value) -> Result<Self> {
+ v.to_simple_value().ok_or_else(|| {
+ Error::Deserialize(format!(
+ "this cannot be deserialized into a simple type: {}",
+ v
+ ))
+ })
+ }
+}
+impl Deserialize for SimpleType {
+ fn from_dhall(v: &Value) -> Result<Self> {
+ v.to_simple_type().ok_or_else(|| {
+ Error::Deserialize(format!(
+ "this cannot be deserialized into a simple type: {}",
+ v
+ ))
+ })
+ }
+}
+
+impl Eq for Value {}
+impl PartialEq for Value {
+ fn eq(&self, other: &Self) -> bool {
+ self.hir == other.hir
+ }
+}
+impl std::fmt::Display for Value {
+ fn fmt(
+ &self,
+ f: &mut std::fmt::Formatter,
+ ) -> std::result::Result<(), std::fmt::Error> {
+ self.to_expr().fmt(f)
+ }
+}