summaryrefslogtreecommitdiff
path: root/dhall/src
diff options
context:
space:
mode:
authorBasile Henry2020-10-18 21:51:38 +0200
committerBasile Henry2020-10-25 15:50:02 +0000
commit0f2522aadcc81481b14c8611db2777670a85ab32 (patch)
tree32d311e0aff29e77b167c95a0051d916b2788c4c /dhall/src
parent1872d6ba12de0e73ef321e026f594d1780e3e084 (diff)
Refactor Text/replace eval
Diffstat (limited to 'dhall/src')
-rw-r--r--dhall/src/builtins.rs71
1 files changed, 29 insertions, 42 deletions
diff --git a/dhall/src/builtins.rs b/dhall/src/builtins.rs
index ed58e14..e80bf6b 100644
--- a/dhall/src/builtins.rs
+++ b/dhall/src/builtins.rs
@@ -410,51 +410,38 @@ fn apply_builtin(b: Builtin, args: Vec<Nir>, env: NzEnv) -> NirKind {
_ => Ret::DoneAsIs,
},
(Builtin::TextReplace, [needle, replacement, haystack]) => {
- match (&*needle.kind(), &*haystack.kind()) {
- (TextLit(n_lit), TextLit(h_lit)) => {
- // The needle and the haystack need to be fully
- // evaluated as Text otherwise no progress can be made
- match (n_lit.as_text(), h_lit.as_text()) {
- (Some(n), Some(h)) => {
- // Helper to match a Nir as a text literal
- fn nir_to_string(n: &Nir) -> Option<String> {
- match &*n.kind() {
- TextLit(r_lit) => r_lit.as_text(),
- _ => None,
- }
- }
+ // Helper to match a Nir as a text literal
+ fn nir_to_string(n: &Nir) -> Option<String> {
+ match &*n.kind() {
+ TextLit(n_lit) => n_lit.as_text(),
+ _ => None,
+ }
+ }
- // When the needle is empty the haystack is returned untouched
- if n.is_empty() {
- Ret::Nir(haystack.clone())
- // Fast case when replacement is fully evaluated
- } else if let Some(r) = nir_to_string(replacement) {
- Ret::Nir(Nir::from_text(h.replace(&n, &r)))
- } else {
- use std::iter::{once, repeat};
+ // The needle and the haystack need to be fully
+ // evaluated as Text otherwise no progress can be made
+ match (nir_to_string(needle), nir_to_string(haystack)) {
+ (Some(n), Some(h)) => {
+ // When the needle is empty the haystack is returned untouched
+ if n.is_empty() {
+ Ret::Nir(haystack.clone())
+ // Fast case when replacement is fully evaluated
+ } else if let Some(r) = nir_to_string(replacement) {
+ Ret::Nir(Nir::from_text(h.replace(&n, &r)))
+ } else {
+ use itertools::Itertools;
- let mut parts = h.split(&n).map(|s| {
- InterpolatedTextContents::Text(
- s.to_string(),
- )
- });
- let replacement =
- InterpolatedTextContents::Expr(
- replacement.clone(),
- );
- let first = parts.next();
- let rest = repeat(replacement)
- .zip(parts)
- .flat_map(|(r, p)| once(r).chain(once(p)));
+ let parts = h.split(&n).map(|s| {
+ InterpolatedTextContents::Text(s.to_string())
+ });
+ let replacement =
+ InterpolatedTextContents::Expr(replacement.clone());
- Ret::Nir(Nir::from_kind(NirKind::TextLit(
- nze::nir::TextLit::new(
- first.into_iter().chain(rest),
- ),
- )))
- }
- }
- _ => Ret::DoneAsIs,
+ Ret::Nir(Nir::from_kind(NirKind::TextLit(
+ nze::nir::TextLit::new(
+ parts.intersperse(replacement),
+ ),
+ )))
}
}
_ => Ret::DoneAsIs,