summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dhall/src/lib.rs64
-rw-r--r--dhall/src/semantics/tck/typecheck.rs4
-rw-r--r--serde_dhall/src/lib.rs47
-rw-r--r--serde_dhall/src/serde.rs4
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)))