summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/src/lib.rs6
-rw-r--r--dhall/src/semantics/nze/nir.rs48
-rw-r--r--dhall/src/simple.rs52
-rw-r--r--serde_dhall/src/lib.rs61
-rw-r--r--serde_dhall/src/static_type.rs8
5 files changed, 138 insertions, 37 deletions
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs
index 0be6db3..25196ba 100644
--- a/dhall/src/lib.rs
+++ b/dhall/src/lib.rs
@@ -30,7 +30,7 @@ pub type ParsedExpr = Expr;
pub type DecodedExpr = Expr;
pub type ResolvedExpr = Expr;
pub type NormalizedExpr = Expr;
-pub use crate::simple::{SValKind, SimpleValue};
+pub use crate::simple::{STyKind, SValKind, SimpleType, SimpleValue};
#[derive(Debug, Clone)]
pub struct Parsed(ParsedExpr, ImportLocation);
@@ -146,6 +146,10 @@ impl Normalized {
pub fn to_simple_value(&self) -> Result<SimpleValue, Expr> {
self.0.to_simple_value().ok_or_else(|| self.to_expr())
}
+ /// Converts a value into a SimpleType.
+ pub fn to_simple_type(&self) -> Result<SimpleType, Expr> {
+ self.0.to_simple_type().ok_or_else(|| self.to_expr())
+ }
/// Converts a value back to the corresponding Hir expression.
pub(crate) fn to_hir(&self) -> Hir {
self.0.to_hir_noenv()
diff --git a/dhall/src/semantics/nze/nir.rs b/dhall/src/semantics/nze/nir.rs
index 9e3644c..4615b39 100644
--- a/dhall/src/semantics/nze/nir.rs
+++ b/dhall/src/semantics/nze/nir.rs
@@ -11,7 +11,7 @@ use crate::syntax::{
Span,
};
use crate::{NormalizedExpr, ToExprOptions};
-use crate::{SValKind, SimpleValue};
+use crate::{STyKind, SValKind, SimpleType, SimpleValue};
/// Stores a possibly unevaluated value. Gets (partially) normalized on-demand, sharing computation
/// automatically. Uses a Rc<RefCell> to share computation.
@@ -176,6 +176,52 @@ impl Nir {
_ => return None,
}))
}
+ pub(crate) fn to_simple_type(&self) -> Option<SimpleType> {
+ Some(SimpleType::new(match self.kind() {
+ NirKind::AppliedBuiltin(BuiltinClosure { b, args, .. })
+ if args.is_empty() =>
+ {
+ match b {
+ Builtin::Bool => STyKind::Bool,
+ Builtin::Natural => STyKind::Natural,
+ Builtin::Integer => STyKind::Integer,
+ Builtin::Double => STyKind::Double,
+ Builtin::Text => STyKind::Text,
+ _ => return None,
+ }
+ }
+ NirKind::AppliedBuiltin(BuiltinClosure {
+ b: Builtin::Optional,
+ args,
+ ..
+ }) if args.len() == 1 => {
+ STyKind::Optional(args[0].to_simple_type()?)
+ }
+ NirKind::AppliedBuiltin(BuiltinClosure {
+ b: Builtin::List,
+ args,
+ ..
+ }) if args.len() == 1 => STyKind::List(args[0].to_simple_type()?),
+ NirKind::RecordType(kts) => STyKind::Record(
+ kts.iter()
+ .map(|(k, v)| Some((k.into(), v.to_simple_type()?)))
+ .collect::<Option<_>>()?,
+ ),
+ NirKind::UnionType(kts) => STyKind::Union(
+ kts.iter()
+ .map(|(k, v)| {
+ Some((
+ k.into(),
+ v.as_ref()
+ .map(|v| Ok(v.to_simple_type()?))
+ .transpose()?,
+ ))
+ })
+ .collect::<Option<_>>()?,
+ ),
+ _ => return None,
+ }))
+ }
pub(crate) fn normalize(&self) {
self.0.normalize()
diff --git a/dhall/src/simple.rs b/dhall/src/simple.rs
index 6457291..9d3846e 100644
--- a/dhall/src/simple.rs
+++ b/dhall/src/simple.rs
@@ -1,6 +1,7 @@
use std::collections::BTreeMap;
-use crate::syntax::LitKind;
+use crate::syntax::{Builtin, LitKind};
+use crate::Normalized;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SimpleValue {
@@ -17,6 +18,24 @@ pub enum SValKind {
Text(String),
}
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct SimpleType {
+ kind: Box<STyKind>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum STyKind {
+ Bool,
+ Natural,
+ Integer,
+ Double,
+ Text,
+ Optional(SimpleType),
+ List(SimpleType),
+ Record(BTreeMap<String, SimpleType>),
+ Union(BTreeMap<String, Option<SimpleType>>),
+}
+
impl SimpleValue {
pub(crate) fn new(kind: SValKind) -> Self {
SimpleValue {
@@ -27,3 +46,34 @@ impl SimpleValue {
self.kind.as_ref()
}
}
+
+impl SimpleType {
+ pub fn new(kind: STyKind) -> Self {
+ SimpleType {
+ kind: Box::new(kind),
+ }
+ }
+ pub fn kind(&self) -> &STyKind {
+ self.kind.as_ref()
+ }
+ pub fn into_normalized(self) -> Normalized {
+ match *self.kind {
+ STyKind::Bool => Normalized::make_builtin_type(Builtin::Bool),
+ STyKind::Natural => Normalized::make_builtin_type(Builtin::Natural),
+ STyKind::Integer => Normalized::make_builtin_type(Builtin::Integer),
+ STyKind::Double => Normalized::make_builtin_type(Builtin::Double),
+ STyKind::Text => Normalized::make_builtin_type(Builtin::Text),
+ STyKind::Optional(t) => {
+ Normalized::make_optional_type(t.into_normalized())
+ }
+ STyKind::List(t) => Normalized::make_list_type(t.into_normalized()),
+ STyKind::Record(kts) => Normalized::make_record_type(
+ kts.into_iter().map(|(k, t)| (k, t.into_normalized())),
+ ),
+ STyKind::Union(kts) => Normalized::make_union_type(
+ kts.into_iter()
+ .map(|(k, t)| (k, t.map(|t| t.into_normalized()))),
+ ),
+ }
+ }
+}
diff --git a/serde_dhall/src/lib.rs b/serde_dhall/src/lib.rs
index 5f386e3..d019238 100644
--- a/serde_dhall/src/lib.rs
+++ b/serde_dhall/src/lib.rs
@@ -183,7 +183,7 @@ pub use value::Value;
// A Dhall value.
#[doc(hidden)]
pub mod value {
- use dhall::{Normalized, NormalizedExpr, Parsed, SimpleValue};
+ use dhall::{Normalized, NormalizedExpr, Parsed, SimpleType, SimpleValue};
use super::de::Error;
use super::Type;
@@ -203,7 +203,7 @@ pub mod value {
let resolved = Parsed::parse_str(s)?.resolve()?;
let typed = match ty {
None => resolved.typecheck()?,
- Some(t) => resolved.typecheck_with(t.as_normalized())?,
+ Some(t) => resolved.typecheck_with(&t.to_normalized())?,
};
Ok(Value(typed.normalize()))
}
@@ -212,6 +212,11 @@ pub mod value {
) -> Result<SimpleValue, NormalizedExpr> {
self.0.to_simple_value()
}
+ pub(crate) fn to_simple_type(
+ &self,
+ ) -> Result<SimpleType, NormalizedExpr> {
+ self.0.to_simple_type()
+ }
}
impl super::de::sealed::Sealed for Value {}
@@ -226,56 +231,46 @@ pub mod value {
// A Dhall type.
#[doc(hidden)]
pub mod ty {
- use dhall::syntax::Builtin;
- use dhall::{Normalized, Parsed};
+ use dhall::{Normalized, STyKind, SimpleType};
use super::de::Error;
- /// A Dhall value
+ /// A Dhall type
#[derive(Debug, Clone, PartialEq, Eq)]
- pub struct Type(Normalized);
+ pub struct Type(SimpleType);
impl Type {
- pub fn from_str(s: &str, ty: Option<&Type>) -> super::de::Result<Self> {
- Type::from_str_using_dhall_error_type(s, ty).map_err(Error::Dhall)
- }
- 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.as_normalized())?,
- };
- Ok(Type(typed.normalize()))
- }
- pub(crate) fn as_normalized(&self) -> &Normalized {
- &self.0
+ pub(crate) fn to_normalized(&self) -> Normalized {
+ self.0.clone().into_normalized()
}
- pub(crate) fn make_builtin_type(b: Builtin) -> Self {
- Type(Normalized::make_builtin_type(b))
+ pub(crate) fn from_simple_type(ty: SimpleType) -> Self {
+ Type(ty)
+ }
+ pub(crate) fn from_stykind(k: STyKind) -> Self {
+ Type(SimpleType::new(k))
}
pub(crate) fn make_optional_type(t: Type) -> Self {
- Type(Normalized::make_optional_type(t.0))
+ Type::from_stykind(STyKind::Optional(t.0))
}
pub(crate) fn make_list_type(t: Type) -> Self {
- Type(Normalized::make_list_type(t.0))
+ Type::from_stykind(STyKind::List(t.0))
}
// Made public for the StaticType derive macro
#[doc(hidden)]
pub fn make_record_type(
kts: impl Iterator<Item = (String, Type)>,
) -> Self {
- Type(Normalized::make_record_type(kts.map(|(k, t)| (k, t.0))))
+ Type::from_stykind(STyKind::Record(
+ kts.map(|(k, t)| (k, t.0)).collect(),
+ ))
}
#[doc(hidden)]
pub fn make_union_type(
kts: impl Iterator<Item = (String, Option<Type>)>,
) -> Self {
- Type(Normalized::make_union_type(
- kts.map(|(k, t)| (k, t.map(|t| t.0))),
+ Type::from_stykind(STyKind::Union(
+ kts.map(|(k, t)| (k, t.map(|t| t.0))).collect(),
))
}
}
@@ -284,7 +279,13 @@ pub mod ty {
impl super::de::Deserialize for Type {
fn from_dhall(v: &super::Value) -> super::de::Result<Self> {
- Ok(Type(v.0.clone()))
+ let sty = v.to_simple_type().map_err(|expr| {
+ Error::Deserialize(format!(
+ "this cannot be deserialized into a simple type: {}",
+ expr
+ ))
+ })?;
+ Ok(Type(sty))
}
}
}
diff --git a/serde_dhall/src/static_type.rs b/serde_dhall/src/static_type.rs
index 921b296..bc5f366 100644
--- a/serde_dhall/src/static_type.rs
+++ b/serde_dhall/src/static_type.rs
@@ -1,4 +1,4 @@
-use dhall::syntax::Builtin;
+use dhall::{STyKind, SimpleType};
use crate::Type;
@@ -18,10 +18,10 @@ pub trait StaticType {
}
macro_rules! derive_builtin {
- ($ty:ty, $builtin:ident) => {
- impl StaticType for $ty {
+ ($rust_ty:ty, $dhall_ty:ident) => {
+ impl StaticType for $rust_ty {
fn static_type() -> Type {
- Type::make_builtin_type(Builtin::$builtin)
+ Type::from_simple_type(SimpleType::new(STyKind::$dhall_ty))
}
}
};