diff options
Diffstat (limited to '')
-rw-r--r-- | dhall/src/lib.rs | 10 | ||||
-rw-r--r-- | dhall/src/semantics/nze/nir.rs | 34 | ||||
-rw-r--r-- | dhall/src/simple.rs | 29 |
3 files changed, 71 insertions, 2 deletions
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index 24e4377..0be6db3 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -9,6 +9,7 @@ mod tests; pub mod error; pub mod semantics; +pub mod simple; pub mod syntax; use std::fmt::Display; @@ -29,6 +30,7 @@ pub type ParsedExpr = Expr; pub type DecodedExpr = Expr; pub type ResolvedExpr = Expr; pub type NormalizedExpr = Expr; +pub use crate::simple::{SValKind, SimpleValue}; #[derive(Debug, Clone)] pub struct Parsed(ParsedExpr, ImportLocation); @@ -53,7 +55,7 @@ pub struct Typed { pub struct Normalized(Nir); /// Controls conversion from `Nir` to `Expr` -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Default)] pub(crate) struct ToExprOptions { /// Whether to convert all variables to `_` pub(crate) alpha: bool, @@ -138,7 +140,11 @@ impl Normalized { /// Converts a value back to the corresponding AST expression. pub fn to_expr(&self) -> NormalizedExpr { - self.0.to_expr(ToExprOptions { alpha: false }) + self.0.to_expr(ToExprOptions::default()) + } + /// Converts a value into a SimpleValue. + pub fn to_simple_value(&self) -> Result<SimpleValue, Expr> { + self.0.to_simple_value().ok_or_else(|| self.to_expr()) } /// Converts a value back to the corresponding Hir expression. pub(crate) fn to_hir(&self) -> Hir { diff --git a/dhall/src/semantics/nze/nir.rs b/dhall/src/semantics/nze/nir.rs index 32ef590..9e3644c 100644 --- a/dhall/src/semantics/nze/nir.rs +++ b/dhall/src/semantics/nze/nir.rs @@ -11,6 +11,7 @@ use crate::syntax::{ Span, }; use crate::{NormalizedExpr, ToExprOptions}; +use crate::{SValKind, SimpleValue}; /// Stores a possibly unevaluated value. Gets (partially) normalized on-demand, sharing computation /// automatically. Uses a Rc<RefCell> to share computation. @@ -142,6 +143,39 @@ impl Nir { pub(crate) fn to_expr_tyenv(&self, tyenv: &TyEnv) -> NormalizedExpr { self.to_hir(tyenv.as_varenv()).to_expr_tyenv(tyenv) } + pub(crate) fn to_simple_value(&self) -> Option<SimpleValue> { + Some(SimpleValue::new(match self.kind() { + NirKind::Lit(lit) => SValKind::Lit(lit.clone()), + NirKind::TextLit(x) => SValKind::Text( + x.as_text() + .expect("Normal form should ensure the text is a string"), + ), + NirKind::EmptyOptionalLit(_) => SValKind::Optional(None), + NirKind::NEOptionalLit(x) => { + SValKind::Optional(Some(x.to_simple_value()?)) + } + NirKind::EmptyListLit(_) => SValKind::List(vec![]), + NirKind::NEListLit(xs) => SValKind::List( + xs.iter() + .map(|v| v.to_simple_value()) + .collect::<Option<_>>()?, + ), + NirKind::RecordLit(kvs) => SValKind::Record( + kvs.iter() + .map(|(k, v)| Some((k.into(), v.to_simple_value()?))) + .collect::<Option<_>>()?, + ), + NirKind::UnionLit(field, x, _) => { + SValKind::Union(field.into(), Some(x.to_simple_value()?)) + } + NirKind::UnionConstructor(field, ty) + if ty.get(field).map(|f| f.is_some()) == Some(false) => + { + SValKind::Union(field.into(), None) + } + _ => return None, + })) + } pub(crate) fn normalize(&self) { self.0.normalize() diff --git a/dhall/src/simple.rs b/dhall/src/simple.rs new file mode 100644 index 0000000..6457291 --- /dev/null +++ b/dhall/src/simple.rs @@ -0,0 +1,29 @@ +use std::collections::BTreeMap; + +use crate::syntax::LitKind; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SimpleValue { + kind: Box<SValKind>, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SValKind { + Lit(LitKind), + Optional(Option<SimpleValue>), + List(Vec<SimpleValue>), + Record(BTreeMap<String, SimpleValue>), + Union(String, Option<SimpleValue>), + Text(String), +} + +impl SimpleValue { + pub(crate) fn new(kind: SValKind) -> Self { + SimpleValue { + kind: Box::new(kind), + } + } + pub fn kind(&self) -> &SValKind { + self.kind.as_ref() + } +} |