diff options
author | Nadrieril | 2019-03-23 23:24:11 +0100 |
---|---|---|
committer | Nadrieril | 2019-03-23 23:24:11 +0100 |
commit | 062fc44a93a18ee432e51db852290ab5849f4dd9 (patch) | |
tree | c9dd53daf9cd99f5dcf982e1d98099a078f63110 /dhall/src | |
parent | f610bc0aac5eaa365c95b489fb2d06cab449ec77 (diff) |
Handle merge and record projection
Diffstat (limited to 'dhall/src')
-rw-r--r-- | dhall/src/normalize.rs | 41 |
1 files changed, 36 insertions, 5 deletions
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), |