summaryrefslogtreecommitdiff
path: root/dhall
diff options
context:
space:
mode:
Diffstat (limited to 'dhall')
-rw-r--r--dhall/src/lib.rs10
-rw-r--r--dhall/src/semantics/nze/nir.rs34
-rw-r--r--dhall/src/simple.rs29
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()
+ }
+}