From 062fc44a93a18ee432e51db852290ab5849f4dd9 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 23 Mar 2019 23:24:11 +0100 Subject: Handle merge and record projection --- dhall/src/normalize.rs | 41 ++++++++++++++++++++++++++++++++++++----- dhall/tests/normalization.rs | 12 ++++++------ 2 files changed, 42 insertions(+), 11 deletions(-) (limited to 'dhall') diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs index 4652b25..2ffa5a5 100644 --- a/dhall/src/normalize.rs +++ b/dhall/src/normalize.rs @@ -276,14 +276,45 @@ where (o, _, _) => BinOp(*o, x, y), }) } - Field(e, x) => { + Merge(x, y, t) => { + let x = normalize_whnf(x); + let y = normalize_whnf(y); + match (x.as_ref(), y.as_ref()) { + (RecordLit(handlers), UnionLit(k, v, _)) => { + match handlers.get(&k) { + Some(h) => { + normalize_whnf(&rc(App(h.clone(), vec![v.clone()]))) + } + None => rc(Merge(x, y, t.clone())), + } + } + _ => rc(Merge(x, y, t.clone())), + } + } + Field(e, l) => { let e = normalize_whnf(e); - match (e.as_ref(), x) { - (RecordLit(kvs), x) => match kvs.get(&x) { + match e.as_ref() { + RecordLit(kvs) => match kvs.get(&l) { Some(r) => normalize_whnf(r), - None => rc(Field(e, x.clone())), + None => rc(Field(e, l.clone())), }, - (_, x) => rc(Field(e, x.clone())), + _ => rc(Field(e, l.clone())), + } + } + Projection(_, ls) if ls.is_empty() => { + rc(RecordLit(std::collections::BTreeMap::new())) + } + Projection(e, ls) => { + let e = normalize_whnf(e); + match e.as_ref() { + RecordLit(kvs) => rc(RecordLit( + ls.iter() + .filter_map(|l| { + kvs.get(l).map(|x| (l.clone(), x.clone())) + }) + .collect(), + )), + _ => rc(Projection(e, ls.clone())), } } _ => Rc::clone(e), diff --git a/dhall/tests/normalization.rs b/dhall/tests/normalization.rs index 9ecad74..5df46a6 100644 --- a/dhall/tests/normalization.rs +++ b/dhall/tests/normalization.rs @@ -13,7 +13,7 @@ norm!(spec_normalization_success_haskell_tutorial_access_0, "haskell-tutorial/ac // norm!(spec_normalization_success_haskell_tutorial_combineTypes_0, "haskell-tutorial/combineTypes/0"); // norm!(spec_normalization_success_haskell_tutorial_combineTypes_1, "haskell-tutorial/combineTypes/1"); // norm!(spec_normalization_success_haskell_tutorial_prefer_0, "haskell-tutorial/prefer/0"); -// norm!(spec_normalization_success_haskell_tutorial_projection_0, "haskell-tutorial/projection/0"); +norm!(spec_normalization_success_haskell_tutorial_projection_0, "haskell-tutorial/projection/0"); // norm!(spec_normalization_success_multiline_escape, "multiline/escape"); // norm!(spec_normalization_success_multiline_hangingIndent, "multiline/hangingIndent"); // norm!(spec_normalization_success_multiline_interesting, "multiline/interesting"); @@ -228,9 +228,9 @@ norm!(spec_normalization_success_unit_ListNormalizeTypeAnnotation, "unit/ListNor norm!(spec_normalization_success_unit_ListReverse, "unit/ListReverse"); norm!(spec_normalization_success_unit_ListReverseEmpty, "unit/ListReverseEmpty"); norm!(spec_normalization_success_unit_ListReverseTwo, "unit/ListReverseTwo"); -// norm!(spec_normalization_success_unit_Merge, "unit/Merge"); +norm!(spec_normalization_success_unit_Merge, "unit/Merge"); norm!(spec_normalization_success_unit_MergeNormalizeArguments, "unit/MergeNormalizeArguments"); -// norm!(spec_normalization_success_unit_MergeWithType, "unit/MergeWithType"); +norm!(spec_normalization_success_unit_MergeWithType, "unit/MergeWithType"); norm!(spec_normalization_success_unit_MergeWithTypeNormalizeArguments, "unit/MergeWithTypeNormalizeArguments"); norm!(spec_normalization_success_unit_Natural, "unit/Natural"); norm!(spec_normalization_success_unit_NaturalBuild, "unit/NaturalBuild"); @@ -302,9 +302,9 @@ norm!(spec_normalization_success_unit_OptionalFoldNone, "unit/OptionalFoldNone") norm!(spec_normalization_success_unit_OptionalFoldSome, "unit/OptionalFoldSome"); norm!(spec_normalization_success_unit_Record, "unit/Record"); norm!(spec_normalization_success_unit_RecordEmpty, "unit/RecordEmpty"); -// norm!(spec_normalization_success_unit_RecordProjection, "unit/RecordProjection"); -// norm!(spec_normalization_success_unit_RecordProjectionEmpty, "unit/RecordProjectionEmpty"); -// norm!(spec_normalization_success_unit_RecordProjectionNormalizeArguments, "unit/RecordProjectionNormalizeArguments"); +norm!(spec_normalization_success_unit_RecordProjection, "unit/RecordProjection"); +norm!(spec_normalization_success_unit_RecordProjectionEmpty, "unit/RecordProjectionEmpty"); +norm!(spec_normalization_success_unit_RecordProjectionNormalizeArguments, "unit/RecordProjectionNormalizeArguments"); norm!(spec_normalization_success_unit_RecordSelection, "unit/RecordSelection"); norm!(spec_normalization_success_unit_RecordSelectionNormalizeArguments, "unit/RecordSelectionNormalizeArguments"); norm!(spec_normalization_success_unit_RecordType, "unit/RecordType"); -- cgit v1.2.3