diff options
author | Nadrieril Feneanar | 2019-08-03 20:16:15 +0200 |
---|---|---|
committer | GitHub | 2019-08-03 20:16:15 +0200 |
commit | 925bf5b5cb7d10301d0a92214bc13d8eb53bf035 (patch) | |
tree | 1012ed5c2443301b7af440a973a9573d3285d743 /dhall/src/phase/normalize.rs | |
parent | 9113e15534f57626ae9be662738e1d3d22434e88 (diff) | |
parent | 6bcb9bed4820f2307b1d3e512fa2d7252ba82f02 (diff) |
Merge pull request #90 from FintanH/fintan/typecheck-combine
Add the typechecking of RecursiveRecordMerge.
Diffstat (limited to 'dhall/src/phase/normalize.rs')
-rw-r--r-- | dhall/src/phase/normalize.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/dhall/src/phase/normalize.rs b/dhall/src/phase/normalize.rs index da19dc1..7d86833 100644 --- a/dhall/src/phase/normalize.rs +++ b/dhall/src/phase/normalize.rs @@ -372,6 +372,60 @@ enum Ret<'a> { Expr(ExprF<Thunk, X>), } +/// Performs an outer join of two HashMaps. +/// +/// # Arguments +/// +/// * `ft` - Will convert the values of the first map +/// into the target value. +/// +/// * `fu` - Will convert the values of the second map +/// into the target value. +/// +/// * `fktu` - Will convert the key and values from both maps +/// into the target type. +/// +/// # Description +/// +/// If the key is present in both maps then the final value for +/// that key is computed via the `fktu` function. Otherwise, the +/// final value will be calculated by either the `ft` or `fu` value +/// depending on which map the key is present in. +/// +/// The final map will contain all keys from the two input maps with +/// also values computed as per above. +pub(crate) fn outer_join<K, T, U, V>( + mut ft: impl FnMut(&T) -> V, + mut fu: impl FnMut(&U) -> V, + mut fktu: impl FnMut(&K, &T, &U) -> V, + map1: &HashMap<K, T>, + map2: &HashMap<K, U>, +) -> HashMap<K, V> +where + K: std::hash::Hash + Eq + Clone, +{ + let mut kvs = HashMap::new(); + + for (k1, t) in map1 { + let v = if let Some(u) = map2.get(k1) { + // The key exists in both maps + // so use all values for computation + fktu(k1, t, u) + } else { + // Key only exists in map1 + ft(t) + }; + kvs.insert(k1.clone(), v); + } + + for (k1, u) in map2 { + // Insert if key was missing in map1 + kvs.entry(k1.clone()).or_insert(fu(u)); + } + + kvs +} + pub(crate) fn merge_maps<K, V>( map1: &HashMap<K, V>, map2: &HashMap<K, V>, |