From 63d3356f40ef48a7735a2151a14ad9952fc245db Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 17 Apr 2019 01:22:28 +0200 Subject: Normalize union constructors --- dhall/src/normalize.rs | 26 ++++++++++++++++++++++---- dhall_core/src/core.rs | 2 ++ dhall_core/src/printer.rs | 14 ++++++++++++-- dhall_core/src/visitor.rs | 7 +++++-- 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>) -> Expr { 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>) -> Expr { 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>) -> Expr { 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 { UnionType(BTreeMap>), /// `< k1 = t1, k2 : t2, k3 >` UnionLit(Label, SubExpr, BTreeMap>), + /// `< k1 : t1, k2 >.k1` + UnionConstructor(Label, BTreeMap>), /// `merge x y : t` Merge(SubExpr, SubExpr, Option), /// `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 Display for ExprF { 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 Display for ExprF { } 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)?, -- cgit v1.2.3