summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dhall/src/normalize.rs26
-rw-r--r--dhall_core/src/core.rs2
-rw-r--r--dhall_core/src/printer.rs14
-rw-r--r--dhall_core/src/visitor.rs7
4 files changed, 41 insertions, 8 deletions
diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs
index 2bbaf52..e0ed96c 100644
--- a/dhall/src/normalize.rs
+++ b/dhall/src/normalize.rs
@@ -234,6 +234,7 @@ fn normalize_ref(expr: &Expr<X, Normalized<'static>>) -> Expr<X, X> {
expr.map_ref_simple(|e| normalize_ref(e.as_ref()));
use WhatNext::*;
+ // TODO: match by move
let what_next = match &expr {
Let(f, _, r, b) => {
let vf0 = &V(f.clone(), 0);
@@ -261,6 +262,13 @@ fn normalize_ref(expr: &Expr<X, Normalized<'static>>) -> Expr<X, X> {
let b2 = subst_shift(vx0, &a.roll(), &b);
Continue(App(b2, iter.map(ExprF::roll).collect()))
}
+ App(UnionConstructor(l, kts), args) => {
+ let mut iter = args.iter();
+ // We know args is nonempty
+ let a = iter.next().unwrap();
+ let e = rc(UnionLit(l.clone(), rc(a.clone()), kts.clone()));
+ Continue(App(e, iter.map(ExprF::roll).collect()))
+ }
BoolIf(BoolLit(true), t, _) => DoneRef(t),
BoolIf(BoolLit(false), _, f) => DoneRef(f),
// TODO: interpolation
@@ -285,16 +293,25 @@ fn normalize_ref(expr: &Expr<X, Normalized<'static>>) -> Expr<X, X> {
let ys = ys.iter().cloned();
Done(NEListLit(xs.chain(ys).collect()))
}
- Merge(RecordLit(handlers), UnionLit(k, v, _), _) => {
- match handlers.get(&k) {
+ Merge(RecordLit(handlers), UnionLit(l, v, _), _) => {
+ match handlers.get(&l) {
Some(h) => Continue(App(h.clone(), vec![v.clone()])),
None => DoneAsIs,
}
}
+ Merge(RecordLit(handlers), UnionConstructor(l, _), _) => {
+ match handlers.get(&l) {
+ Some(h) => DoneRefSub(h),
+ None => DoneAsIs,
+ }
+ }
Field(RecordLit(kvs), l) => match kvs.get(&l) {
Some(r) => DoneRefSub(r),
None => DoneAsIs,
},
+ Field(UnionType(kts), l) => {
+ Done(UnionConstructor(l.clone(), kts.clone()))
+ }
Projection(_, ls) if ls.is_empty() => {
Done(RecordLit(std::collections::BTreeMap::new()))
}
@@ -349,7 +366,7 @@ mod spec_tests {
}
norm!(success_haskell_tutorial_access_0, "haskell-tutorial/access/0");
- // norm!(success_haskell_tutorial_access_1, "haskell-tutorial/access/1");
+ norm!(success_haskell_tutorial_access_1, "haskell-tutorial/access/1");
// norm!(success_haskell_tutorial_combineTypes_0, "haskell-tutorial/combineTypes/0");
// norm!(success_haskell_tutorial_combineTypes_1, "haskell-tutorial/combineTypes/1");
// norm!(success_haskell_tutorial_prefer_0, "haskell-tutorial/prefer/0");
@@ -560,7 +577,8 @@ mod spec_tests {
norm!(success_unit_ListReverse, "unit/ListReverse");
norm!(success_unit_ListReverseEmpty, "unit/ListReverseEmpty");
norm!(success_unit_ListReverseTwo, "unit/ListReverseTwo");
- // norm!(success_unit_Merge, "unit/Merge");
+ norm!(success_unit_Merge, "unit/Merge");
+ norm!(success_unit_MergeEmptyAlternative, "unit/MergeEmptyAlternative");
norm!(success_unit_MergeNormalizeArguments, "unit/MergeNormalizeArguments");
norm!(success_unit_MergeWithType, "unit/MergeWithType");
norm!(success_unit_MergeWithTypeNormalizeArguments, "unit/MergeWithTypeNormalizeArguments");
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs
index 075ef81..2dfa4d8 100644
--- a/dhall_core/src/core.rs
+++ b/dhall_core/src/core.rs
@@ -190,6 +190,8 @@ pub enum ExprF<SubExpr, Label, Note, Embed> {
UnionType(BTreeMap<Label, Option<SubExpr>>),
/// `< k1 = t1, k2 : t2, k3 >`
UnionLit(Label, SubExpr, BTreeMap<Label, Option<SubExpr>>),
+ /// `< k1 : t1, k2 >.k1`
+ UnionConstructor(Label, BTreeMap<Label, Option<SubExpr>>),
/// `merge x y : t`
Merge(SubExpr, SubExpr, Option<SubExpr>),
/// `e.x`
diff --git a/dhall_core/src/printer.rs b/dhall_core/src/printer.rs
index bb3c427..4d1ae2d 100644
--- a/dhall_core/src/printer.rs
+++ b/dhall_core/src/printer.rs
@@ -92,9 +92,9 @@ impl<SE: Display + Clone, N, E: Display> Display for ExprF<SE, Label, N, E> {
write!(f, "{} = {}", k, v)
})?,
UnionType(a) => fmt_list("< ", " | ", " >", a, f, |(k, v), f| {
- write!(f, "{} : ", k)?;
+ write!(f, "{}", k)?;
if let Some(v) = v {
- v.fmt(f)?
+ write!(f, ": {}", v)?;
}
Ok(())
})?,
@@ -108,6 +108,16 @@ impl<SE: Display + Clone, N, E: Display> Display for ExprF<SE, Label, N, E> {
}
f.write_str(" >")?
}
+ UnionConstructor(x, map) => {
+ fmt_list("< ", " | ", " >", map, f, |(k, v), f| {
+ write!(f, "{}", k)?;
+ if let Some(v) = v {
+ write!(f, ": {}", v)?;
+ }
+ Ok(())
+ })?;
+ write!(f, ".{}", x)?
+ }
Embed(a) => a.fmt(f)?,
Note(_, b) => b.fmt(f)?,
}
diff --git a/dhall_core/src/visitor.rs b/dhall_core/src/visitor.rs
index 1ea3fb1..c123275 100644
--- a/dhall_core/src/visitor.rs
+++ b/dhall_core/src/visitor.rs
@@ -178,11 +178,14 @@ where
RecordType(kts) => RecordType(btmap(kts, v)?),
RecordLit(kvs) => RecordLit(btmap(kvs, v)?),
UnionType(kts) => UnionType(btoptmap(kts, v)?),
- UnionLit(k, x, kvs) => UnionLit(
+ UnionLit(k, x, kts) => UnionLit(
v.visit_label(k)?,
v.visit_subexpr(x)?,
- btoptmap(kvs, v)?,
+ btoptmap(kts, v)?,
),
+ UnionConstructor(x, kts) => {
+ UnionConstructor(v.visit_label(x)?, btoptmap(kts, v)?)
+ }
Merge(x, y, t) => Merge(
v.visit_subexpr(x)?,
v.visit_subexpr(y)?,