diff options
-rw-r--r-- | dhall/src/lib.rs | 64 | ||||
-rw-r--r-- | dhall/src/semantics/tck/typecheck.rs | 4 | ||||
-rw-r--r-- | serde_dhall/src/lib.rs | 47 | ||||
-rw-r--r-- | serde_dhall/src/serde.rs | 4 |
4 files changed, 86 insertions, 33 deletions
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index 25196ba..60b7a0e 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -49,11 +49,18 @@ pub struct Typed { } /// A normalized expression. -/// -/// Invariant: the contained expression must be in normal form, #[derive(Debug, Clone)] pub struct Normalized(Nir); +/// A Dhall value. +#[derive(Debug, Clone)] +pub struct Value { + /// Invariant: in normal form + pub(crate) hir: Hir, + simple_val: Option<SimpleValue>, + simple_ty: Option<SimpleType>, +} + /// Controls conversion from `Nir` to `Expr` #[derive(Copy, Clone, Default)] pub(crate) struct ToExprOptions { @@ -99,8 +106,8 @@ impl Resolved { pub fn typecheck(&self) -> Result<Typed, TypeError> { Ok(Typed::from_tir(typecheck(&self.0)?)) } - pub fn typecheck_with(self, ty: &Normalized) -> Result<Typed, TypeError> { - Ok(Typed::from_tir(typecheck_with(&self.0, ty.to_hir())?)) + pub(crate) fn typecheck_with(self, ty: &Hir) -> Result<Typed, TypeError> { + Ok(Typed::from_tir(typecheck_with(&self.0, ty)?)) } /// Converts a value back to the corresponding AST expression. pub fn to_expr(&self) -> ResolvedExpr { @@ -137,6 +144,13 @@ impl Normalized { pub fn encode(&self) -> Result<Vec<u8>, EncodeError> { binary::encode(&self.to_expr()) } + pub fn to_value(&self) -> Value { + Value { + hir: self.to_hir(), + simple_val: self.0.to_simple_value(), + simple_ty: self.0.to_simple_type(), + } + } /// Converts a value back to the corresponding AST expression. pub fn to_expr(&self) -> NormalizedExpr { @@ -200,6 +214,36 @@ impl Normalized { } } +impl Value { + /// Parse a string into a Value, and optionally ensure that the value matches the provided type + /// annotation. + pub fn from_str_with_annot( + s: &str, + ty: Option<&Self>, + ) -> Result<Self, Error> { + let resolved = Parsed::parse_str(s)?.resolve()?; + let typed = match ty { + None => resolved.typecheck()?, + Some(ty) => resolved.typecheck_with(&ty.hir)?, + }; + Ok(typed.normalize().to_value()) + } + + /// Converts a Value into a SimpleValue. + pub fn to_simple_value(&self) -> Option<SimpleValue> { + self.simple_val.clone() + } + /// Converts a Value into a SimpleType. + pub fn to_simple_type(&self) -> Option<SimpleType> { + self.simple_ty.clone() + } + + /// Converts a value back to the corresponding AST expression. + pub(crate) fn to_expr(&self) -> NormalizedExpr { + self.hir.to_expr(ToExprOptions::default()) + } +} + macro_rules! derive_traits_for_wrapper_struct { ($ty:ident) => { impl std::cmp::PartialEq for $ty { @@ -274,3 +318,15 @@ impl Display for Normalized { self.to_expr().fmt(f) } } + +impl Eq for Value {} +impl PartialEq for Value { + fn eq(&self, other: &Self) -> bool { + self.hir == other.hir + } +} +impl Display for Value { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + self.to_expr().fmt(f) + } +} diff --git a/dhall/src/semantics/tck/typecheck.rs b/dhall/src/semantics/tck/typecheck.rs index 173b76d..9fa33f2 100644 --- a/dhall/src/semantics/tck/typecheck.rs +++ b/dhall/src/semantics/tck/typecheck.rs @@ -808,8 +808,8 @@ pub(crate) fn typecheck<'hir>(hir: &'hir Hir) -> Result<Tir<'hir>, TypeError> { /// Like `typecheck`, but additionally checks that the expression's type matches the provided type. pub(crate) fn typecheck_with<'hir>( hir: &'hir Hir, - ty: Hir, + ty: &Hir, ) -> Result<Tir<'hir>, TypeError> { - let ty = typecheck(&ty)?.eval_to_type(&TyEnv::new())?; + let ty = typecheck(ty)?.eval_to_type(&TyEnv::new())?; type_with(&TyEnv::new(), hir, Some(ty)) } diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs index d019238..1f7ecf8 100644 --- a/serde_dhall/src/lib.rs +++ b/serde_dhall/src/lib.rs @@ -183,38 +183,26 @@ pub use value::Value; // A Dhall value. #[doc(hidden)] pub mod value { - use dhall::{Normalized, NormalizedExpr, Parsed, SimpleType, SimpleValue}; + use dhall::{SimpleType, SimpleValue}; use super::de::Error; use super::Type; /// A Dhall value #[derive(Debug, Clone, PartialEq, Eq)] - pub struct Value(pub(crate) Normalized); + pub struct Value(pub(crate) dhall::Value); impl Value { pub fn from_str(s: &str, ty: Option<&Type>) -> super::de::Result<Self> { - Value::from_str_using_dhall_error_type(s, ty).map_err(Error::Dhall) + let ty = ty.map(|t| t.to_dhall_value()); + let val = dhall::Value::from_str_with_annot(s, ty.as_ref()) + .map_err(Error::Dhall)?; + Ok(Value(val)) } - fn from_str_using_dhall_error_type( - s: &str, - ty: Option<&Type>, - ) -> dhall::error::Result<Self> { - let resolved = Parsed::parse_str(s)?.resolve()?; - let typed = match ty { - None => resolved.typecheck()?, - Some(t) => resolved.typecheck_with(&t.to_normalized())?, - }; - Ok(Value(typed.normalize())) - } - pub(crate) fn to_simple_value( - &self, - ) -> Result<SimpleValue, NormalizedExpr> { + pub(crate) fn to_simple_value(&self) -> Option<SimpleValue> { self.0.to_simple_value() } - pub(crate) fn to_simple_type( - &self, - ) -> Result<SimpleType, NormalizedExpr> { + pub(crate) fn to_simple_type(&self) -> Option<SimpleType> { self.0.to_simple_type() } } @@ -226,12 +214,21 @@ pub mod value { Ok(v.clone()) } } + + impl std::fmt::Display for Value { + fn fmt( + &self, + f: &mut std::fmt::Formatter, + ) -> Result<(), std::fmt::Error> { + self.0.fmt(f) + } + } } // A Dhall type. #[doc(hidden)] pub mod ty { - use dhall::{Normalized, STyKind, SimpleType}; + use dhall::{STyKind, SimpleType}; use super::de::Error; @@ -240,8 +237,8 @@ pub mod ty { pub struct Type(SimpleType); impl Type { - pub(crate) fn to_normalized(&self) -> Normalized { - self.0.clone().into_normalized() + pub(crate) fn to_dhall_value(&self) -> dhall::Value { + self.0.clone().into_normalized().to_value() } pub(crate) fn from_simple_type(ty: SimpleType) -> Self { @@ -279,10 +276,10 @@ pub mod ty { impl super::de::Deserialize for Type { fn from_dhall(v: &super::Value) -> super::de::Result<Self> { - let sty = v.to_simple_type().map_err(|expr| { + let sty = v.to_simple_type().ok_or_else(|| { Error::Deserialize(format!( "this cannot be deserialized into a simple type: {}", - expr + v )) })?; Ok(Type(sty)) diff --git a/serde_dhall/src/serde.rs b/serde_dhall/src/serde.rs index 9cb67d1..5d8fcf3 100644 --- a/serde_dhall/src/serde.rs +++ b/serde_dhall/src/serde.rs @@ -19,10 +19,10 @@ where T: serde::Deserialize<'a>, { fn from_dhall(v: &Value) -> Result<Self> { - let sval = v.to_simple_value().map_err(|expr| { + let sval = v.to_simple_value().ok_or_else(|| { Error::Deserialize(format!( "this cannot be deserialized into the serde data model: {}", - expr + v )) })?; T::deserialize(Deserializer(Cow::Owned(sval))) |