From 5176b900bf22cf264ce7e75dd416e9e822719168 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 6 Apr 2019 13:25:10 +0200 Subject: Upgrade map to traverse --- dhall_core/src/core.rs | 126 +++++++++++++++++++++++++++++++++---------------- dhall_core/src/text.rs | 22 ++++++--- 2 files changed, 102 insertions(+), 46 deletions(-) (limited to 'dhall_core') diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index a9033f3..355f625 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -12,6 +12,13 @@ pub type Double = NaiveDouble; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum X {} +pub fn trivial_result(x: Result) -> T { + match x { + Ok(x) => x, + Err(e) => match e {}, + } +} + /// Double with bitwise equality #[derive(Debug, Copy, Clone)] pub struct NaiveDouble(f64); @@ -362,83 +369,122 @@ impl ExprF { } #[inline(always)] - pub fn map( + pub fn traverse( self, map_subexpr: F1, map_under_binder: F2, map_note: F3, map_embed: F4, mut map_label: F5, - ) -> ExprF + ) -> Result, Err> where L: Ord, L2: Ord, - F1: FnMut(SE) -> SE2, - F2: FnOnce(&L, SE) -> SE2, - F3: FnOnce(N) -> N2, - F4: FnOnce(E) -> E2, - F5: FnMut(L) -> L2, + F1: FnMut(SE) -> Result, + F2: FnOnce(&L, SE) -> Result, + F3: FnOnce(N) -> Result, + F4: FnOnce(E) -> Result, + F5: FnMut(L) -> Result, { let mut map = map_subexpr; - fn vec U>(x: Vec, f: F) -> Vec { + fn vec Result>( + x: Vec, + f: F, + ) -> Result, Err> { x.into_iter().map(f).collect() } - fn btmap( + fn opt Result>( + x: Option, + f: F, + ) -> Result, Err> { + Ok(match x { + Some(x) => Some(f(x)?), + None => None, + }) + } + fn btmap( x: BTreeMap, mut fk: FK, mut fv: FV, - ) -> BTreeMap + ) -> Result, Err> where K: Ord, L: Ord, - FK: FnMut(K) -> L, - FV: FnMut(T) -> U, + FK: FnMut(K) -> Result, + FV: FnMut(T) -> Result, { - x.into_iter().map(|(k, v)| (fk(k), fv(v))).collect() + x.into_iter().map(|(k, v)| Ok((fk(k)?, fv(v)?))).collect() } use crate::ExprF::*; - match self { - Var(V(l, n)) => Var(V(map_label(l), n)), + Ok(match self { + Var(V(l, n)) => Var(V(map_label(l)?, n)), Lam(l, t, b) => { - let b = map_under_binder(&l, b); - Lam(map_label(l), map(t), b) + let b = map_under_binder(&l, b)?; + Lam(map_label(l)?, map(t)?, b) } Pi(l, t, b) => { - let b = map_under_binder(&l, b); - Pi(map_label(l), map(t), b) + let b = map_under_binder(&l, b)?; + Pi(map_label(l)?, map(t)?, b) } Let(l, t, a, b) => { - let b = map_under_binder(&l, b); - Let(map_label(l), t.map(&mut map), map(a), b) + let b = map_under_binder(&l, b)?; + Let(map_label(l)?, opt(t, &mut map)?, map(a)?, b) } - App(f, args) => App(map(f), vec(args, map)), - Annot(x, t) => Annot(map(x), map(t)), + App(f, args) => App(map(f)?, vec(args, map)?), + Annot(x, t) => Annot(map(x)?, map(t)?), Const(k) => Const(k), Builtin(v) => Builtin(v), BoolLit(b) => BoolLit(b), NaturalLit(n) => NaturalLit(n), IntegerLit(n) => IntegerLit(n), DoubleLit(n) => DoubleLit(n), - TextLit(t) => TextLit(t.map(map)), - BinOp(o, x, y) => BinOp(o, map(x), map(y)), - BoolIf(b, t, f) => BoolIf(map(b), map(t), map(f)), - EmptyListLit(t) => EmptyListLit(map(t)), - NEListLit(es) => NEListLit(vec(es, map)), - EmptyOptionalLit(t) => EmptyOptionalLit(map(t)), - NEOptionalLit(e) => NEOptionalLit(map(e)), - RecordType(kts) => RecordType(btmap(kts, map_label, map)), - RecordLit(kvs) => RecordLit(btmap(kvs, map_label, map)), - UnionType(kts) => UnionType(btmap(kts, map_label, map)), + TextLit(t) => TextLit(t.traverse(map)?), + BinOp(o, x, y) => BinOp(o, map(x)?, map(y)?), + BoolIf(b, t, f) => BoolIf(map(b)?, map(t)?, map(f)?), + EmptyListLit(t) => EmptyListLit(map(t)?), + NEListLit(es) => NEListLit(vec(es, map)?), + EmptyOptionalLit(t) => EmptyOptionalLit(map(t)?), + NEOptionalLit(e) => NEOptionalLit(map(e)?), + RecordType(kts) => RecordType(btmap(kts, map_label, map)?), + RecordLit(kvs) => RecordLit(btmap(kvs, map_label, map)?), + UnionType(kts) => UnionType(btmap(kts, map_label, map)?), UnionLit(k, v, kvs) => { - UnionLit(map_label(k), map(v), btmap(kvs, map_label, map)) + UnionLit(map_label(k)?, map(v)?, btmap(kvs, map_label, map)?) } - Merge(x, y, t) => Merge(map(x), map(y), t.map(map)), - Field(e, l) => Field(map(e), map_label(l)), - Projection(e, ls) => Projection(map(e), vec(ls, map_label)), - Note(n, e) => Note(map_note(n), map(e)), - Embed(a) => Embed(map_embed(a)), - } + Merge(x, y, t) => Merge(map(x)?, map(y)?, opt(t, map)?), + Field(e, l) => Field(map(e)?, map_label(l)?), + Projection(e, ls) => Projection(map(e)?, vec(ls, map_label)?), + Note(n, e) => Note(map_note(n)?, map(e)?), + Embed(a) => Embed(map_embed(a)?), + }) + } + + #[inline(always)] + pub fn map( + self, + mut map_subexpr: F1, + map_under_binder: F2, + map_note: F3, + map_embed: F4, + mut map_label: F5, + ) -> ExprF + where + L: Ord, + L2: Ord, + F1: FnMut(SE) -> SE2, + F2: FnOnce(&L, SE) -> SE2, + F3: FnOnce(N) -> N2, + F4: FnOnce(E) -> E2, + F5: FnMut(L) -> L2, + { + trivial_result(self.traverse( + |x| Ok(map_subexpr(x)), + |l, x| Ok(map_under_binder(l, x)), + |x| Ok(map_note(x)), + |x| Ok(map_embed(x)), + |x| Ok(map_label(x)), + )) } #[inline(always)] diff --git a/dhall_core/src/text.rs b/dhall_core/src/text.rs index 9500f32..7c0e2b4 100644 --- a/dhall_core/src/text.rs +++ b/dhall_core/src/text.rs @@ -34,18 +34,28 @@ pub enum InterpolatedTextContents { } impl InterpolatedText { - pub fn map(self, mut f: F) -> InterpolatedText + pub fn traverse( + self, + mut f: F, + ) -> Result, E> where - F: FnMut(SubExpr) -> SubExpr2, + F: FnMut(SubExpr) -> Result, { - InterpolatedText { + Ok(InterpolatedText { head: self.head.clone(), tail: self .tail .into_iter() - .map(|(e, s)| (f(e), s.clone())) - .collect(), - } + .map(|(e, s)| Ok((f(e)?, s.clone()))) + .collect::>()?, + }) + } + + pub fn map(self, mut f: F) -> InterpolatedText + where + F: FnMut(SubExpr) -> SubExpr2, + { + crate::trivial_result(self.traverse(|e| Ok(f(e)))) } pub fn as_ref(&self) -> InterpolatedText<&SubExpr> { -- cgit v1.2.3